【Ruby】Ruby on Rails Part6

このエントリーをはてなブックマークに追加
952934:2009/04/19(日) 20:26:48 ID:GcnrJHDf
>>934 分かる方いらっしゃましたらご教示頂けると幸いです><
953nobodyさん:2009/04/19(日) 21:43:31 ID:???
>>952
map.connect ':controller/:id/bbb/ccc', :action => 'bbb_ccc'

954nobodyさん:2009/04/19(日) 21:44:38 ID:???
書いてから思ったが、そういうのがaaa限定なら変にいろいろ受け付けるようにせず
map.connect 'aaa/:id/bbb/ccc', :controller => 'aaa', :action => 'bbb_ccc'
のほうがいいか。

955952:2009/04/20(月) 01:59:43 ID:PwSyAV4m
>>954 でいけました!ありがとうございましたm(_ _)m
956nobodyさん:2009/04/20(月) 10:04:09 ID:???
質問です。

あるページにジャンプする際に、非ログイン状態だと403を返すようにしたいのですが、
これはどこにコードを記述するべきでしょうか?
957nobodyさん:2009/04/20(月) 14:25:50 ID:???
コントローラだろjk
restful authenticationつかってない?
958nobodyさん:2009/04/24(金) 20:51:26 ID:/YVXcJLc
すいません質問させてください。
(User.find 133).friends(:all, :conditions => ["age = ?", 20])
こんな感じのことをしたいのですが、どうすればいいでしょうか。
(.friendsでは配列が返ってくる・・)
なんかうまい書き方があったら教えていただけると幸いです><
959nobodyさん:2009/04/24(金) 21:08:16 ID:???
User.find(133).friends.find_all_by_age(20)
960nobodyさん:2009/04/24(金) 21:37:48 ID:???
多用するならnamed_scopeで見易く。

class Friend < AR::Base
named_scope :of_age, lambda {|age| { :conditions => [ 'age = ?', age ] } }
end

User.find(1333).friends.of_age(20)
961nobodyさん:2009/04/24(金) 22:21:15 ID:???
ActiveRecord で質問です。
:conditions に ハッシュを渡せば 各キーが AND で結合されますが、

product = Product.find(:all,
 :conditions => {
 :price => 1000,
 :kubun => [6, 7, 8]}
)
select * from products where price = 1000 and kubun in (6, 7, 8)

key > value とかはできまませんか?
以下のような(在庫数が 10 以上 20 以下)SQL を実行させる Ruby コードを書きたいです。
10..20 として between を使いたいところですが、画面側で 10以上 だけしか指定されない場合があるため、使えません。

select * from products where price = 1000 and kubun in (6, 7, 8) and zaiko > 10 and zaiko < 20
962nobodyさん:2009/04/24(金) 22:38:10 ID:???
conditions = 'price = ? AND kubun in (?) AND zaiko > ?'
args = [ 1000, [6,7,8, 10] ]

if upper
conditions += ' AND zaiko < ?'
args << upper
end

find(:all, :conditions => [ conditions, *args ])

963nobodyさん:2009/04/24(金) 22:38:51 ID:???
10まで中に入れてしまった。察っして。
964nobodyさん:2009/04/24(金) 22:55:22 ID:???
レスどうもありがとうございます。

やはり :conditions にハッシュを渡す方法じゃなく、
:conditoins => 配列 のやり方
(配列の第一要素が SQL の文字列、第二要素以降がバインド変数のパラメータ)
じゃないとできないですか。

その方法でやってみます。
965nobodyさん:2009/04/24(金) 23:32:47 ID:???
あまりありがたみはないが
:conditions => [ 'price = :p', { :p => 1000 } ] とも書けるな。
966nobodyさん:2009/04/25(土) 00:01:47 ID:???
web側で入力項目が15コぐらいあり、それがセッションに入っている。
その15コがそのまま SQL のパラメータになるんだけど、session オブジェクトをそのまま ActiveRecord のモデルのメソッドに
渡してもよい?

それとも何か Condition クラスを作り、そこに詰めてからモデルに渡すべき?

Java 的発想だと、Http 層を 永続化層に持って行くのはよくないので、なんらかのオブジェクトに詰め直してから
渡しますが、Rails でもそうしたほうがいいでしょうか。

session はハッシュなので、そのハッシュから部分的なハッシュを作り直し、ハッシュ渡しにしようかと思いましたが、
入力項目が多いので、抜けがあると間違いの元なので、単独の Condition クラスを定義しようと思っています。
967nobodyさん:2009/04/25(土) 07:37:56 ID:???
セッションがWeb上で取得したパラメータをそのまま持つよりは、
最初からConditionオブジェクトに詰めて永続化しておき、Sessionでは
参照キーだけを持っておくという形にする気がする。
968nobodyさん:2009/04/25(土) 13:09:16 ID:???
そのまんま入れてます。
Railsでは詰めなおしてもあまり意味ないかも。
入力項目のチェックはActiveRecordがするんだし。
969nobodyさん:2009/04/25(土) 13:27:35 ID:???
rspec-rrとか使っている人いない?
標準のrspecとmock、stubとどう違ってくるんでしょ
970nobodyさん:2009/04/25(土) 16:44:24 ID:???
そのなんらかのオブジェクトがRailsでいうモデルだろ
テーブルとモデルを1:1で紐づけるのがactive recordパターン
テーブルとモデルをn:nで紐づけるのがdata mapperパターン
Webはフォームの入力項目 ≒ テーブルなのでactive recordパターンが広く使われている
なので、sessionでもつハッシュの構造はDBにあわせた方がベター
それができない場合は、モデルにハッシュ構造の変換処理を書くのが作法
ARにもバリューオブジェクトあるけど、ちょっと用途が違う気がする
971nobodyさん:2009/04/25(土) 23:25:28 ID:???
>>966
凝った検証処理が必要ないなら Hash#assert_valid_keys でチェックしてから Hash#slice で切り出して渡すかな。
972nobodyさん:2009/04/26(日) 05:03:44 ID:???
お前ら rails でファイルアップロード用のファイル管理ライブラリとかプラグインてないんでしょうか?
アップロードした画像をリサイズしてくれたり、ファイル一覧をサムネイルで表示してくれたり、
選んだの削除できたり
そういうステキなのキボン
973nobodyさん:2009/04/26(日) 14:44:10 ID:ZTlDJFDt
>>972
作ってくだ(ry
974966:2009/04/26(日) 18:58:31 ID:???
みなさまレスどうもありがとうございます。
結論としては、session オブジェクトをモデルのメソッドに渡すのをやめ、
新規に condition オブジェクトを作ることにしました。

>>970
今回のケースでは、
画面の入力項目はそのまま SQL のパラメータになるけど、モデル(テーブル)の属性にはならないのです。
>>961 (これも自分なのだが) のように、商品マスタの price が ○円以上○円以下で、kubun が■or■で・・・・といった条件が延々と並ぶ。
だからモデルクラスはそのまま使えませんでした。

>>971
ruby リファレンスマニュアルの hash をみたところ、assert_valid_keys や slice というメソッドはありませんでした。
これは自分で特異メソッドとして定義せよ、ということ?
975nobodyさん:2009/04/26(日) 19:04:34 ID:???
976nobodyさん:2009/04/27(月) 16:33:28 ID:ty2d5Btl
>>959
>>960
ありがとうございますm(_ _)m

すいません他にも質問したいことができました。

if true
User.friends
elseif
User.parents
else
User.childern
end

のような処理をしたいとき、
User.xxx のxxxの部分を変数みたいにして、条件分岐なしで一行で書くことはできないでしょうか??

ご教示いただけると幸いです。
977nobodyさん:2009/04/27(月) 20:17:33 ID:ty2d5Btl
すいません分かりにくかったかもしれないと思ったので書き直します・・

if x='friends'
User.friends
elseif x='pearents'
User.parents
else x='children'
User.childern
end

を一行で書けないか・・みたいな感じです。
978nobodyさん:2009/04/27(月) 20:24:34 ID:???
User.send(x)
979nobodyさん:2009/04/27(月) 20:26:28 ID:???
> 977
User.method(x).call
980nobodyさん:2009/04/28(火) 00:13:18 ID:???
すみません、知恵を貸してください。

現在、items(仮)というテーブル(id, name)からnameを条件にレコードを検索し、
will_paginateを使用して表示している機能があります。

その機能を、検索条件との「完全一致」「前方一致」「部分一致」の順に並び替えたいのですが、
なにかいい方法はないでしょうか…?

複雑なSQLを書けばいけるとは思いますが、何か他に方法がないか模索してします。


981nobodyさん:2009/04/28(火) 01:29:09 ID:???
完全一致、前方一致、部分一致の3検索をする以上selectが3回必要なのは仕方ないんじゃないだろうか。
Item.find_by_sql <<SQL
SELECT * FROM (
SELECT 1 AS sort_key, * FROM items WHERE name LIKE "aaa"
UNION SELECT 2 AS sort_key, * FROM items WHERE name LIKE "a%"
UNION SELECT 3 AS sort_key, * FROM items WHERE name LIKE "%a%") ORDER BY sort_key ASC
SQL
とか。(てきとう)

トータルの該当検索件数が大したことないなら、
それぞれの一致方式で個別にfindした結果を連結し、そいつに、
will_paginateが必要とするメソッドを特異メソッドとして実装するという手もある。
(total_pages, current_page, previous_page, next_pageメソッドを定義すればいい)


あと、likeの引数に任意の外部入力文字列を安全に埋め込むのは結構面倒だと思うのでがんばって。
982nobodyさん:2009/04/28(火) 03:22:51 ID:???
>>981
そのままだとaaaというnameを持つitemが3つのselectそれぞれから出てくるな。
要distinct?
983nobodyさん:2009/04/28(火) 06:13:49 ID:N2IsGKnP
スレ終了まぎわですが、おしえてください。

ユーザ毎にカード型データベースを持たせたいと思っています。
自由にフィールド数を定義でき、入力フィールドも並び替えできるようにしたいと
思ってます(イメージ的には簡易的なデヂエみたいなの)

そこで質問ですが、ユーザ操作でtableを生成することはrails的作法で有りなのでしょうか?
ある程度入力値にルールを設けたいので、validateほにゃららを定義できれば..と
欲張っているんですが、modelに手をいれる必要がありますよね?
generatorとして作らないといけないのでしょうか?
984nobodyさん:2009/04/28(火) 11:26:55 ID:???
>>980
1.ページごとのレコードをDBで絞り込んでRailsで表示させる
2.該当のレコードをすべて取得してRailsで表示させる

のどちらかだと思う

「1」はDB依存だからどのDBを使ってるかで答えは変わる
「2」は大量のレコードが返ってくるなら普通やらない

そもそも部分一致はインデックスを使えないから、
普通のRDBの使い方ではやるべきじゃないな。
全文検索機能を使ってるなら、また答えは変わる。

情報が不足しすぎて答えられないな
985nobodyさん:2009/04/28(火) 21:47:12 ID:???
>>983
ユーザーのアカウントごとに構造の異なるARモデルを扱うアプリを運用しています。
テーブルスキーマ自体はいまのところユーザーの好き勝手ではなく、アカウント作成時に
カラムの型やオプションをYAMLファイルで定義したものを使っているので
>>983ほど柔軟ではないです。

AR::Base.connection.create_table {|t| ... } でそれらのカラム定義から t.column を呼び、
Class.new(AR::Base) して動的に作ったモデルクラスで set_table_nameすれば、ファイル
に書き出さずともモデルとして使用できます。

カラムの数や順序を自由に変更できるようにするには、ユーザーの変更操作に同期して
schema_statements.rbにあるメソッドを呼んで処理してやる必要があると思います。
986nobodyさん:2009/04/29(水) 01:18:41 ID:MR+/ICUP
さすが マーチンファウラーお気に入りのベストパートナー
世界に羽ばたく
Ruby on Railsオフショアアジャイル開発
http://www.tech-arts.co.jp/news-and-topics/press-releases/20090427.html
987nobodyさん:2009/04/29(水) 01:23:54 ID:???
相当失敗した話を聞いてるが、まだオフショアとか言ってるところあるのか。
しかもこれからってw

圧力釜もろくに作れない国に発注するって顧客に対する背信行為だと思う。
メーカーなみに製造管理するならいいけど、
工場ほど単純作業じゃないから無理だわな。
988nobodyさん:2009/04/29(水) 01:34:38 ID:???
日本の技術者=マトモ、は既に幻想だろうに。きっちり技術階層ができてるし、新人はゆとってるし。
で、コストの高い日本の不勉強さん使うよりオフショアの方が質がいい。そんな感じだろーね。

けど、実際は難しいけど。上手くいかせたくない心理が働いてそう。
989nobodyさん:2009/04/29(水) 01:48:39 ID:???
うまくいかせたくない心理なんて働かねーよ。顧客の窓口は日本だぞ。
失敗すれば全部かぶるんだよ。幻想はおまえだ
990nobodyさん:2009/04/29(水) 10:49:26 ID:???
RubyConf Chinaみたいなのもやるようだし、中国でもRuby熱は高まって
きてるのかね。

個人的には、中国とかインドの新興国はJavaばっかりやってるイメージ
があるが。
991980:2009/04/29(水) 11:25:21 ID:???
>>981-982,984
回答ありがとうございました。

>>981さんの方法が、自分でもわかりやすいかなという感じです。

>>982
まったくそのとおりで、要distinctです。
重複を省くための条件が長くなってしまうので、この方法でやるか悩んでいます。

>>984
実際には食品をDB(mysql5)から検索するシステムです。
DBに「牛乳」「牛乳(低脂肪)」「牛乳(濃厚)」「加工牛乳」というレコードがあった場合、
「牛乳」という検索ワードで上記4レコードは表示する必要があります。

なので、
select * from items where name like '%検索文字列%'
でも必要な情報は取れるのですが、完全一致したものは上に表示したいという
気持ちもあります。

ていうかlikeの部分一致ってINDEX使わないんですね・・・。
992nobodyさん:2009/04/29(水) 11:57:35 ID:???
オフショア≒カスがコスト改善したつもりになって社内で評価されるためのまやかしw
993nobodyさん:2009/04/29(水) 14:00:00 ID:???
>>991
なるほど。likeの部分一致の遅さを許容できるならやり方はあるよ。

3回SQLを打つのは速度や負荷を考えるとやらない方がいいと思う。
すでに話題になってるように重複の問題もあるし。

やり方の一つとしては「ソートキーを作る」。
MySQLはほとんどやらないし、いま手元に環境はないから検証できないのだが、
case文はサポートされていたと思う。

select column_1, columnt_2, column_3,
case
when name = '牛乳' then 0
else 1
end match
from items
where name like '%牛乳%'
order by match, sort_key

などとやれば完全一致したものは「match」列に「0」が、そうでないものは「1」が返るはず。
これを第1ソートキーにすればいい。
部分一致や後方一致もちょっと調べたところ、
文字列比較関数なるものをを使えばできるんじゃないだろうか。
優先させたい条件順に番号をふればきれいに並ぶと思う。

これはSQLネタのように思うので、
これ以上知りたければSQLスレがいいだろう。
あるのか知らないけど。

あともし解決したら、差し支えない範囲で解決策をレスしてほしい。
ほかの人が参考にできるから。
聞いてわかってさよならが多くなってるからね。
994nobodyさん:2009/04/29(水) 21:57:49 ID:???
>>993
ありがとうございます。
なるほど・・・。その方法はいいですね。

>あともし解決したら、差し支えない範囲で解決策をレスしてほしい。
了解です。該当機能が動くようになった時にでも。

995981:2009/04/29(水) 23:40:19 ID:???
>>981『「完全一致」「前方一致」「部分一致」でソート』が動くようになりましたので、早速ご報告を。

結論から言えば、sqlで解決しました。以下バージョン等・・・
Rails2.3.2
will_paginateは確か2.2.2か2.0.2だったような・・・。今日現在の「最新」です。
dbはmysql5.0.67

なおwill_paginateの文献をググると、paginate_by_sqlメソッドを自前で追加する
tipが良く見つかりましたが、最新ではソース追加なしでpaginate_by_sqlが使えました。

■牛乳の例でのsql分

select
*,
(
case
when name = '牛乳' then 0
else
case
when name like '牛乳%' then 1
else 2
end
end
) as sort_key

from
items
where
name like '%牛乳%'
996981続き:2009/04/29(水) 23:45:05 ID:???
部分一致のsqlは遅いかもしれませんが、データ自体は4000件程度で増えることは
ほとんどないので、コレで意向と思います。

ソースは変えてありますが、下のような感じで対応しました。

#コントローラ
def コントローラのメソッド

search = params[:search] #検索画面から検索文字列を取得
sql = "select *,(case when name = \'#{search}\' then 0 else case when name like '\'#{search}\'%' then 1 else 2 end end) as sort_key from items where name like \'%#{search}\'%
@results = Item.paginate_by_sql(sql, :page => params[:page], :per_page => 30)

end


#ビュー

<% @results.each{|item| %>
<%= item.name %><br>
<% end %>


>>981,982,984,993
答えてくださった方、ありがとうございました。
997981続き:2009/04/29(水) 23:53:52 ID:???
うう・・・
動いてるソースから書き換えたのでいろいろ間違えてます・・・><
order byがないと修正した意味ないっス〜・・・。そのあたりは流れから脳内変換してください><

すみません、スレ汚し失礼しました。
998nobodyさん:2009/04/30(木) 00:17:59 ID:???
>>995
フィードバックありがとう。強要してすまんね。
paginate_by_sqlは知らなかったから参考になった。
999nobodyさん:2009/04/30(木) 23:12:06 ID:???
次スレ

【Ruby】Ruby on Rails Part7
http://pc11.2ch.net/test/read.cgi/php/1241100447/
1000nobodyさん:2009/04/30(木) 23:18:02 ID:???
1000ならrubyの指輪を唄いたくなる
10011001
このスレッドは1000を超えました。
もう書けないので、新しいスレッドを立ててくださいです。。。