我有3个模型,Shop
Mall
和Sale
。 Mall
has_many Shops
,Shop
belongs_to a Mall
and has_many Sales
,Sale
belongs_to a Shop
。我想要做的是当我去一个特定的商场show
页面时,我希望它只有属于该特定商城的商店的销售才出现在该页面上(商城展示)页)。所以我在商城控制器的show动作中尝试了很多不同的方法,但我一直收到这个错误:
未定义的方法'销售'为零:NilClass
现在这是我的商场控制器:
class MallsController < ApplicationController
before_action :set_mall, only: [:show, :edit, :update, :destroy]
# GET /malls/1
# GET /malls/1.json
def show
@shops = @mall.shops.all
@sales = @shop.sales.where('offer_end >= ?', Date.today).order('discount_to DESC')
end
private
# Use callbacks to share common setup or constraints between actions.
def set_mall
@mall = Mall.find(params[:id])
end
end
shop.rb:
class Shop < ActiveRecord::Base
has_many :categorizations
has_many :categories, :through => :categorizations
has_many :mall_shops
has_many :malls, :through => :mall_shops
has_many :sales, dependent: :destroy
validates :name, presence: true, uniqueness: true
end
mall.rb
class Mall < ActiveRecord::Base
has_many :mall_shops
has_many :shops, :through => :mall_shops
validates :name, presence: true, uniqueness: true
end
sale.rb:
class Sale < ActiveRecord::Base
belongs_to :shop
end
mall_shop.rb
class MallShop < ActiveRecord::Base
belongs_to :shop
belongs_to :mall
end
答案 0 :(得分:3)
这不起作用:
def show
@shops = @mall.shops.all
@sales = @shop.sales.where('offer_end >= ?', Date.today).order('discount_to DESC')
end
在这里,您要定义@shops
这是一组商店,然后您在未定义的.sales
变量上调用@shop
。
但是,即使您将变量更改为@shops
,它也无法正常工作,因为.sales
是Shop
实例上的方法。
为了解决这个问题,我们希望在一次扫描中使用连接尽可能多地加载。
首先删除set_mall
回调,因为我们需要对此操作的加载进行更细粒度的控制:
before_action :set_mall, only: [:edit, :update, :destroy]
然后在show动作中,您要加载mall并在一次扫描中加入相关记录。但是,在加载销售时,您可能需要单独进行查询。
def show
@mall = Mall.eager_load(shops: :sales).find(params[:id])
@sales = Sale.joins(:shop)
.where(shop_id: @mall.shops.ids)
.where('offer_end >= ?', Date.today)
.order(discount_to: :desc)
end
您希望在单独的查询中获取@sales
的原因是您需要进行LEFT OUTER
加入,或者您没有在第一个查询中获得没有销售的商店,您还需要如果你想单独列出它们,可以遍历商店集合以收集所有销售。
答案 1 :(得分:0)
您没有@shop
定义为何获得undefined method 'sales' for nil:NilClass