[英]Pulling data from different tables into a single view
我最近开始学习Ruby on Rails,现在正在开发我的第一个电子商务Web应用程序。 应用程序数据库目前有两个表: products
和variants
products
包含id
, name
, description
等。每种产品可能有几种变体。
variants
包含id
, product_id
, price
, image
等。它还具有一个布尔字段default_var
,用于确定用户首次看到该产品时应在页面上显示的默认变体。
这些模型如下所示:
class Product < ActiveRecord::Base
has_many :variants
end
class Variant < ActiveRecord::Base
belongs_to :product
scope :default, -> {where(dafault_var: 1)}
end
我希望在索引页面上能够显示产品列表以及旁边的图像,价格和说明,因此信息应该是两个表中值的组合。
在index.erb视图文件中,如果我尝试使用each
方法遍历产品数组,则必须使用index变量:
<% @products.each do |product| %>
我想不出一种通过此局部变量访问变体控制器方法的方法。 从variants
表中获取price
和image
等数据的最佳方法是什么? 我想将视图中的Ruby代码保持在最低限度。
控制器当前具有以下代码:
class ProductsController < ApplicationController
def index
@products = Product.paginate(:page => params[:page], :per_page => 5)
#@products = Product.all
end
...
class VariantsController < ApplicationController
def index
@product = Product.find(params[:id])
@variants = @product.variants
end
end
基本上,您可以直接从product
获取variants
<% @products.each do |product| %> <% product.variants.each do |variant| %> ...render your variant... <% end %> <% end %>
稍后将导致N + 1查询问题,因为每次您从product
获得variants
时,都会运行查询。 因此,我们可以在ProductsController
为@products
进行@products
加载
@products = Product.includes(:variants).paginate(:page => params[:page], :per_page => 5)
@variants
, VariantsController
中的@variants
都没有绑定到ProductsController
, VariantsController
的实例变量将用于变量视图。 您处于产品视图中。
因为您有一个包含图片和价格的默认变体,所以我会这样做
class Product < ActiveRecord::Base
def default_variant
self.variants.find_by_default_var(1)
end
end
<% @products.each do |product| %>
<ul>
<li><%= product.description %></li>
<li><%= product.default_variant.price %></li>
<li><%= image_tag(product.default_variant.image) %></li>
</ul>
<% end %>
ActiveRecord
访问variants
是使用:
#app/views/products/index.html.erb
<% @products.each do |product| %>
<% @product.variants.each do |variant| %>
<%= variant.name %>
<% end %>
<% end %>
由于您使用的是has_many
,因此可以将default
变体指定为关联,甚至可以使用ActiveRecord关联扩展 :
#app/models/product.rb
class Product < ActiveRecord::Base
has_many :variants do
def default
find_by default_var: true #-> @product.variants.default
end
end
has_one :default_variant, -> { find_by(default_var: true) }, class_name: "Variant", foreign_key: :product_id #-> @product.default_variant
end
这将允许您调用:
#app/views/products/index.html.erb
<% @products.each do |product| %>
<%= product.default_variant.name %>
<% end %>
-
我不知道这会对n+1
等产生什么影响
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.