如何加载具有关联模型的特定ID的记录 - Rails 4

时间:2016-03-07 15:28:56

标签: ruby-on-rails

我有3个模型,Shop MallSaleMall has_many ShopsShop belongs_to a Mall and has_many SalesSale 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

2 个答案:

答案 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,它也无法正常工作,因为.salesShop实例上的方法。

为了解决这个问题,我们希望在一次扫描中使用连接尽可能多地加载。

首先删除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