2016-03-07 36 views
0

我有3個型號,ShopMallSale。 a Mall has_many ShopsShop belongs_to a Mall and has_many Sales,and Sale belongs_to a Shop。我想要做的是,當我去特定商城的show頁面時,我想讓它只屬於屬於該特定商場的商店的銷售額顯示在該頁面上(商場展示頁面)。於是,我嘗試過許多不同的方式在商場的控制器的表演動作要做到這一點,但我不斷收到此錯誤:如何使用相關模型的特定ID加載記錄 - 導軌4

undefined method 'sales' for nil: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

通過你的模型重新看完後,我看你有'mall_shops'。這張桌子是什麼樣的? –

+0

問題是你沒有定義'@ shop',所以是錯誤。 – Pavan

+0

@JustinLicata我更新了包含mall_shop的問題。 max給出的答案解決了我的問題,但是如果您有其他解決方案,請隨時分享。 –

回答

3

這是行不通的:

def show 
    @shops = @mall.shops.all 
    @sales = @shop.sales.where('offer_end >= ?', Date.today).order('discount_to DESC') 
    end 

在這裏,您正在定義@shops這是一組商店,然後您在未定義的@shop變量上調用.sales

但是,即使您將變量更改爲@shops,由於.salesShop的實例上的方法,所以它不會起作用。

爲了解決這個問題,我們希望使用連接儘可能地在一次掃描中加載。

首先拆下set_mall回調,因爲我們需要在裝載了這個動作有點更細粒度的控制:

before_action :set_mall, only: [:edit, :update, :destroy] 

然後在要載入商場和一個掃加入相關記錄顯示行動。但是,在加載銷售時,您可能需要執行單獨的查詢。

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加入或不銷售沒有拿到商店在第一個查詢,你也將需要通過迭代如果你想單獨列出他們的商店收集所有的銷售。

+0

在旁註中,您可能想要改進模型的命名,因爲它很混亂。您可能想要調用'Shop' - >'Chain'或'Brand'和'MallShop' - >'Shop'或'Store'。此外,您可能需要處理當地商店可能參與或不參與銷售的情況。 – max

+0

這工作謝謝!你方法中的一些東西對我來說並不熟悉,比如eager_load和join(即時通訊仍然是初學者)。只是想知道爲什麼我需要刪除set_mall?即使我保存它,它也能正常工作。 –

+0

您希望刪除'set_mall'以避免額外的SQL查詢。從性能角度來看,限制往返數據庫的數量總是很好。正如你已經注意到它會反正工作,但它是不太理想的。 – max

0

@shop定義你沒有,這就是爲什麼你所得到的undefined method 'sales' for nil:NilClass