<%=h @user.varieties.find_by_product_id(product.id).name %>
以下是我的两个问题:
(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可以将苹果添加到他们的页面。如果这就是他们想要展示的全部内容,那就必须是好的。然而,他们还可以通过包括他们携带的苹果类型(如富士,麦金托什等)来添加更多细节。品种不仅仅是一个详细的产品。换句话说,我不能让每个产品都像苹果 - 富士,苹果 - 麦金托什。它们需要是两个独立的模型。
在用户页面(即“显示”视图)上,我需要能够显示产品和品种(如果有的话)。系统需要了解这些品种是否与特定用户的特定产品相关联。
根据我收到的第一个答案,我修改了我的模型,如下面的答案中所述。每个品种属于一种产品,即富士仅属于苹果产品,它是产品表中的独特ID。并且,产品具有许多品种,即苹果产品可能具有5或10种不同的品种。
然而,它变得更加复杂,因为每个用户可能拥有不同的产品/品种组合。例如,Topps杂货店(用户)可能拥有富士和麦金托什(品种)的苹果(产品)。但是,Publix杂货店(用户)可能拥有红色美味的苹果(产品)和盛会(品种)。
在用户页面上,我希望能够调出用户携带的每个产品,然后在用户选择任何品种时显示与这些产品相关的品种。
当我在show视图中尝试下面列出的代码时,我收到以下错误:#:
的未定义方法`user_product'<% @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>
答案 0 :(得分: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 %>
当然不需要将它拆分成部分(在这个例子中,可能有点荒谬),但它有助于分离不同的部分,特别是如果你想要添加更多东西来显示。
并回答你的问题:
将所有逻辑移动到控制器和模型可能不是一个好主意,因为他们不应该知道(或关心)你想如何显示数据。所以这只是准备它的问题。
@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
答案 1 :(得分:0)
MikeH
您可能在此处输入错误,@user.user_product
应为@user.user_products
当我尝试下面列出的代码时 在节目视图中,我得到以下内容 错误:未定义的方法`user_product' 对于#:
<% @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。
只是一个想法。