質問の下部にある更新を参照してください。
新しい機能を追加するためにアプリにいくつかの調整を加える必要がありましたが、変更により、以前は完全に機能していた:uniqオプションが壊れたようです。
設定は次の
#User.rb
とおりです。has_many:products、:through =>:seasons、:uniq => true
has_many:varieties、:through =>:seasons、:uniq => true
has_many:seasons
#product.rb
has_many:seasons
has_many:users、:through =>:seasons、:uniq => true
has_many:varieties
#season.rb
所属_to:製品
belongs_to:さまざまな
belongs_to:ユーザー
named_scope:by_product_name、:joins =>:product、:order =>'products.name'
#variety.rb
所属する:product
has_many:seasons
has_many:users、:through =>:seasons、:uniq => true
まず、比較するベースラインがあるように、現在壊れているビューの以前のバージョンを示したいと思います。以下のビューは、ユーザーに属する製品と品種をプルアップしています。以下の両方のバージョンで、同じ製品/品種をユーザーに割り当てたので、ログはまったく同じユースケースを調べます。
#user/show
<% @user.products.each do |product| %>
<%= link_to product.name, product %>
<% @user.varieties.find_all_by_product_id(product.id).each do |variety| %>
<%=h variety.name.capitalize %></p>
<% end %>
<% end %>
これは機能します。各商品を1つだけ表示し、次に各商品の品種を表示します。以下のログでは、製品ID1に3つの関連する品種があります。また、製品ID43には何もありません。
上記のコードのログ出力は次のとおりです。
Product Load (11.3ms) SELECT DISTINCT `products`.* FROM `products` INNER JOIN `seasons` ON `products`.id = `seasons`.product_id WHERE ((`seasons`.user_id = 1)) ORDER BY name, products.name
Product Columns (1.8ms) SHOW FIELDS FROM `products`
Variety Columns (1.9ms) SHOW FIELDS FROM `varieties`
Variety Load (0.7ms) SELECT DISTINCT `varieties`.* FROM `varieties` INNER JOIN `seasons` ON `varieties`.id = `seasons`.variety_id WHERE (`varieties`.`product_id` = 1) AND ((`seasons`.user_id = 1)) ORDER BY name
Variety Load (0.5ms) SELECT DISTINCT `varieties`.* FROM `varieties` INNER JOIN `seasons` ON `varieties`.id = `seasons`.variety_id WHERE (`varieties`.`product_id` = 43) AND ((`seasons`.user_id = 1)) ORDER BY name
さて、上記のすべてがうまく機能していた以前のバージョンです。新しいバージョンでは、と呼ばれる結合テーブルにいくつかの列を追加し、seasons
それらの列をクエリする一連のカスタムメソッドを作成しました。その結果、seasons
モデル 上のこれらのメソッドにアクセスできるように、上記のビューコードに次の変更を加えました。
<% @user.seasons.by_product_name.each do |season| %>
<%= link_to season.product.name, season.product %>
#Note: I couldn't get this loop to work at all, so I settled for the following:
#<% @user.varieties.find_all_by_product_id(product.id).each do |variety| %>
<%=h season.variety.name.capitalize %>
<%end%>
<%end%>
そのためのログ出力は次のとおりです。
SQL (0.9ms) SELECT count(DISTINCT "products".id) AS count_products_id FROM "products" INNER JOIN "seasons" ON "products".id = "seasons".product_id WHERE (("seasons".user_id = 1))
Season Load (1.8ms) SELECT "seasons".* FROM "seasons" INNER JOIN "products" ON "products".id = "seasons".product_id WHERE ("seasons".user_id = 1) AND ("seasons".user_id = 1) ORDER BY products.name
Product Load (0.7ms) SELECT * FROM "products" WHERE ("products"."id" = 43) ORDER BY products.name
CACHE (0.0ms) SELECT "seasons".* FROM "seasons" INNER JOIN "products" ON "products".id = "seasons".product_id WHERE ("seasons".user_id = 1) AND ("seasons".user_id = 1) ORDER BY products.name
Product Load (0.4ms) SELECT * FROM "products" WHERE ("products"."id" = 1) ORDER BY products.name
Variety Load (0.4ms) SELECT * FROM "varieties" WHERE ("varieties"."id" = 2) ORDER BY name
CACHE (0.0ms) SELECT * FROM "products" WHERE ("products"."id" = 1) ORDER BY products.name
Variety Load (0.4ms) SELECT * FROM "varieties" WHERE ("varieties"."id" = 8) ORDER BY name
CACHE (0.0ms) SELECT * FROM "products" WHERE ("products"."id" = 1) ORDER BY products.name
Variety Load (0.4ms) SELECT * FROM "varieties" WHERE ("varieties"."id" = 7) ORDER BY name
CACHE (0.0ms) SELECT * FROM "products" WHERE ("products"."id" = 43) ORDER BY products.name
CACHE (0.0ms) SELECT count(DISTINCT "products".id) AS count_products_id FROM "products" INNER JOIN "seasons" ON "products".id = "seasons".product_id WHERE (("seasons".user_id = 1))
CACHE (0.0ms) SELECT "seasons".* FROM "seasons" INNER JOIN "products" ON "products".id = "seasons".product_id WHERE ("seasons".user_id = 1) AND ("seasons".user_id = 1) ORDER BY products.name
CACHE (0.0ms) SELECT * FROM "products" WHERE ("products"."id" = 1) ORDER BY products.name
CACHE (0.0ms) SELECT * FROM "products" WHERE ("products"."id" = 1) ORDER BY products.name
CACHE (0.0ms) SELECT * FROM "varieties" WHERE ("varieties"."id" = 8) ORDER BY name
私は2つの問題を抱えています:
(1):uniqオプションが。に対して機能していませんproducts
。同じ製品の3つの異なるバージョンがページに表示されています。
(2):uniqオプションが。に対して機能していませんvarieties
。これについてはまだ検証を設定していません。ユーザーが同じ種類を2回入力すると、ページに表示されます。以前の作業バージョンでは、これは当てはまりませんでした。
私が必要とする結果は、特定のIDに対して1つの製品のみが表示され、そのIDに関連付けられているすべての種類がそのような一意の製品とともに表示されることです。
私が目立つのは、最新のログ出力でのSQL呼び出しです。個別の呼び出しに「カウント」を追加しています。なぜそれをしているのか、それが問題の兆候であるのかどうかはわかりません。この未解決の灯台チケットは関連している可能性があるようですが、同じ問題かどうかはわかりません:https ://rails.lighthouseapp.com/projects/8994/tickets/2189-count-breaks-sqlite -has_many-through-association-collection-with-named-scope
アップデート
問題は、named_scopeがシーズンごとに1回呼び出されることだと思います。named_scopeには、返品される商品をシーズンIDで絞り込むものが必要です。
現在起こっていることは次のとおりです。
ユーザー=ユーザー
の季節を取得=ユーザーの季節を取得(たとえば、ユーザーには3つの季節があります)
製品=製品を
取得製品+=製品を取得
製品+=製品を取得
それぞれの商品をください
つまり、何が起こっているのかというと、uniqが壊れているのではなく、名前付きスコープにデリメータがないということです。(おもう)。
次のことを試しましたが、この例外がスローされます:ハッシュの奇数リスト
named_scope :by_product_name, lambda { |seasons| { season_ids = seasons.map { |season| season.id }; :joins => :product, :conditions => { :seasons { :id => season_id } } :order => 'products.name' } }
アイデア?
アップデート#2
さて、今私はそれがスコープされた名前ではないかもしれないと思っています。
では#user/show
、名前付きスコープをバイパスするようにループを変更しました。
<% @user.seasons.each do |season| %>
<%= link_to season.product.name, season.product %>
#Note: I couldn't get this loop to work at all, so I settled for the following:
#<% @user.varieties.find_all_by_product_id(product.id).each do |variety| %>
<%=h season.variety.name.capitalize %>
<%end%>
<%end%>
上記は名前付きスコープを使用していませんが、それでも同じ結果が得られます。つまり、1つだけではなく、各製品のすべてのインスタンスがまだ表示されています。
最初のループを作成する上記のコードは、この質問の冒頭にリストした元のコードと同じです。違いは、このコードがループしてseasons
、にヒットするproducts
のに対し、元のコードはループしていることproducts
です。この違いは問題が隠れているところですが、私はそれを修正する方法がわかりません。
また、元の質問で、品種ループも機能させることができなかったと述べました。すぐ上のコードでコメントされた行を見ることができます。製品ではなく季節をループするときに、Railsがその品種のループにヒットすると、名前エラーがスローされます。
undefined local variable or method `product'
それは同じ問題の別の症状かもしれないようですか?
他のアイデアはありますか?