1

アップデート

わかりました。品種については、次のように呼び出す必要がありました。

<%=h @user.varieties.find_by_product_id(product.id).name %>

ここに私の2つの質問があります:

(1) 結合モデルを呼び出していないため、レコードの編集/削除時に問題が発生しますか? Ryan Bates がこの点を強調しているビデオを見たことがありますが、ここで結合モデルを参照しようとしてもうまくいきません。言い換えれば、上記のコードは を介し​​て呼び出す必要がありますuser_productsか?

結合テーブルを参照する次のコードを使用すると、結合テーブルからのみ表示することができvariety_idます (結合テーブルには品種の名前列がないため)。このコードを結合テーブルで参照する方法がわかりませんvariety_idが、バラエティ テーブルに移動して、「名前」列からバラエティの実際の名前を取得します。

<% @user.products.each do |product| %>
   <% @user.user_products.find_by_product_id(product.id).variety_id %>
<% end %> 

(2)この複雑なものはビューレイヤーに適切に配置されていますか、それともモデルまたはコントローラーに移動するためのより良い方法はありますか?

ありがとう。

以下の元の質問は現在解決されています...

私は次のモデルを持っています:
- ユーザー
- 製品
- 品種 - user_products

これが私がやろうとしていることの現実世界のバージョンです。User が食料品店だとしましょう。製品はリンゴのような果物です。そして品種は、フジやマッキントッシュなどのリンゴの種類です。

次のようなアプリを作成する必要があります。

  • ユーザーは自分のページに多くの種類の製品を追加できます。製品には複数の品種を含めることができますが、ユーザーは品種を含める必要はありません。たとえば、Topps Grocery Store はページにリンゴを追加できます。彼らが表示したいのはそれだけであれば、それで問題ありません。ただし、フジ、マッキントッシュなど、運ぶリンゴの種類を含めることで、さらに詳細を追加することもできます。品種は単なる詳細な製品ではありません。つまり、それぞれの商品をりんご - ふじ、りんご - マッキントッシュにすることはできません。それらは 2 つの別個のモデルである必要があります。

  • ユーザーのページ (つまり、「表示」ビュー) で、製品と品種 (存在する場合) の両方を表示できる必要があります。システムは、品種がこの特定のユーザーの特定の製品に関連付けられていることを理解する必要があります。

受け取った最初の回答に続いて、以下の回答で説明されているようにモデルを修正しました。各品種は 1 つの製品に属します。つまり、フジは製品テーブルの個別の ID であるリンゴ製品のみに属します。また、製品にはさまざまな種類があります。つまり、リンゴ製品には 5 つまたは 10 種類の異なる種類がある場合があります。

ただし、各ユーザーがさまざまな製品/品種の組み合わせを持っている可能性があるため、さらに複雑になります。たとえば、Topps 食料品店 (ユーザー) には、fuji と mcintosh (品種) のリンゴ (製品) があるとします。しかし、Publix の食料品店 (ユーザー) には、赤いおいしいリンゴ (製品) とガラ (品種) がある場合があります。

ユーザーページでは、ユーザーが持っている各製品を呼び出し、ユーザーが品種を選択した場合、それらの各製品に関連する品種を表示できるようにしたいと考えています。

以下に示すコードをショー ビューで実行しようとすると、次のエラーが表示されます: undefined method `user_product' for #:

<% @user.products.each do |product| %>
   <% @user.user_products.find_by_product_id(product.id).varieties %>
<% end %>

一方、あなたがくれた他のオプション (以下にリスト) を試すと、ページが読み込まれ、SQL クエリがログに正しく表示されますが、ページに種類が表示されません。クエリに一致する必要があるデータベース内のレコード。詳細は以下...

<% @user.products.each do |product| %>
   <% @user.varieties.find_by_product_id(product.id) %>
<% end %>    

このコードは、次の SQL クエリを実行します。

User Load (0.7ms) SELECT * FROM "users" WHERE ("users"."id" = 2)

Variety Load (0.5ms) SELECT "varieties".* FROM "varieties" INNER JOIN "user_product" ON "varieties".id = "user_products".variety_id WHERE (("seasons".user_id = 2))

レイアウト/アプリケーション内のレンダリング テンプレート
ユーザー/ショーのレンダリング

Product Load (0.7ms) SELECT "products".* FROM "products" INNER JOIN "user_product" ON "products".id = "user_products".product_id WHERE (("user_products".user_id = 2))

Variety Load (0.4ms) SELECT "varieties".* FROM "varieties" INNER JOIN "user_product" ON "varieties".id = "user_products".variety_id WHERE ("varieties"."product_id" = 1) AND (("user_products".user_id = 2)) LIMIT 1

Variety Load (0.2ms) SELECT "varieties".* FROM "varieties" INNER JOIN "user_products" ON "varieties".id = "user_products".variety_id WHERE ("varieties"."product_id" = 2) AND (("user_products".user_id = 2)) LIMIT 1

上記の場合、私が見ているユーザーuser_id=2, he does have product_id=1 and product_id=2 in the database. And, in the user_products table, I do have a few records that list this user_id connected to each of these product_ids and associated with some variety_ids.

最後に、次のことを試すと:

<% @user.products.each do |product| %>
   <%=h @user.user_products.find_by_product_id(product.id) %>
<% end %>

各レコードのビューに次のように表示されます。#<User_product:0x4211bb0>

4

2 に答える 2

0

MikeH

ここにタイプミスがあるかもしれませんが@user.user_product@user.user_products

ショービューで以下にリストされているコードを試してみると、次のエラーが発生します:undefined method `user_product'for#:

<% @user.products.each do |product| %>  
  <% @user.user_product.find_by_product_id(product.id).varieties %>  
<% end %>

また、「Fuji」、「Macintosh」、「Apples」などの製品がある階層型システムを検討することもできます。

「Fuji」と「Macintosh」では、「parent_id」列が「Apples」のIDに設定されます。

ちょっとした考え。

于 2009-09-19T08:33:47.800 に答える
0

彼らの見方では、製品と多対多の関係を持っていないということです。あなたはその特定の品種の製品にそれを持っています(もしあれば)。したがって、それを追跡するために、追加のモデルを使用します。そうすれば、製品と品種の間の関係も保つことができます。

モデル:

class User < ActiveRecord::Base
  has_many :user_products, :dependent => :destroy
  has_many :products, :through => :user_products
  has_many :varieties, :through => :user_products
end

class UserProduct < ActiveRecord::Base
  belongs_to :user
  belongs_to :product
  belongs_to :variety
end

class Product < ActiveRecord::Base
  has_many :varieties
end

class Variety < ActiveRecord::Base
  belongs_to :product
end

コントローラー:

class UserProductsController < ApplicationController
    before_filter do 
        @user = User.find(params['user_id'])
    end


    def create
      product = Product.find(params['product_id'])
      variety = Variety.find(params['variety_id']) if params['variety_id']

      @user_product = UserProduct.new
      @user_product.user = user
      @user_product.product = product
      @user_product.variety = variety
      @user_product.save
    end

    def destroy
        # Either do something like this:
        conditions = {:user_id => @user.id}
        conditions[:product_id] = params[:product_id] if params[:product_id]
        conditions[:variety_id] = params[:variety_id] if params[:variety_id]

        UserProduct.destroy_all conditions
    end
end

ビュー: 品種をさまざまな製品にグループ化することに興味がなく、それらをリストとして配置するだけで十分な場合は、次のようにします。

# users/show.html.erb
<%= render @user.user_products %>

# user_products/_user_product.html.erb
<%= h user_product.product.name %> 
<%= h user_product.variety.name if user_product.variety %>

それ以外の場合は、もう少し複雑なものを追加する必要があります。アソシエーション プロキシを使用してモデルとコントローラを配置できる場合もありますが、その点についてはお答えできません。

# users/show
<% for product in @user.products do %>
    <%= product.name %>
    <%= render :partial => 'variety', 
        :collection => @user.varieties.find_by_product_id(product.id) %>
<% end %>

# users/_variety
<%= variety.name %> 

もちろん、部分的に分割する必要はありません (この例では、少しばかげているかもしれません) が、特に表示するものをさらに追加したい場合は、さまざまな部分を分離するのに役立ちます。

そしてあなたの質問に答えるために:

  1. UserProduct は結合モデルであるため、個々の ID を追跡する必要はありません。User、Product、Variety があります (これらの場合は存在します)。必要なのはそれだけです。その組み合わせは一意であるため、削除するレコードを見つけることができます。また、結合モデルは編集しないでください (これらのフィールドよりも多くの属性が含まれていない場合)。関連付けを保持するだけなので、作成または削除のいずれかです。
  2. これは基本的に表示するものなので、ビューに配置するのが最善です。もちろん、コントローラーまたはモデルを使用して、次のようにしてすべての製品と品種を事前に収集することもできます。

すべてのロジックをコントローラーとモデルに移動することは、データの表示方法を認識 (または気に) する必要がないため、おそらく良い考えではありません。ですから、十分に準備するだけです。

@products_for_user = []
@user.products.each do |product|
 collected_product = {:product => product, 
                      :varieties => @user.varieties.find_by_product_id(product.id)}
  @products_for_user << collected_product
end
于 2009-09-18T11:37:21.737 に答える