2017-05-09 66 views
2

考慮:是否可以在Rails模型中自動返回虛擬屬性?

class Foo 
    has_one :bar 

    def bar_name 
    bar.name 
    end 
end 

class Bar 
    belongs_to :foo 
end 

在控制檯或一個觀點,我可以@foo.bar_name得到'baz'

我知道我可以@foo.as_json(methods: :bar_name)得到{"id"=>"abc123", "bar_name"=>"baz"}

我也可以使屬性非規範化並使它非虛擬化,但在這種情況下我寧願不這樣做。

是否有可能自動返回包含虛擬屬性的模型?

#<Foo id: "abc123", bar_name: "baz">

我想這樣做,因爲我與構建模型嵌套集合的大型對象,而as_json呼叫從我的抽象化了。

+0

我不明白,你想向客戶端發送'#'或者你希望''Foo'對象在控制檯中被打印出來(例如'puts fooobj#=>#')? – niceman

+0

假設我沒有發送任何東西給客戶端。我只想將方法的結果顯示在控制檯中,而不顯式調用方法。 –

+2

你想在'as_json'響應中使用這個嗎?如果是這樣,你可以在模型本身重新定義'as_json'。如果你想在對象表示中使用它,你可以重新定義'inspect' – engineersmnky

回答

2

不是100%肯定我明白如果您關注的是有關as_json但如果是這樣,這將工作

class Foo 
    has_one :bar 

    def bar_name 
    bar.name 
    end 
    def as_json(options={}) 
    super(options.merge!(methods: :bar_name)) 
    end 
end 

現在,在默認情況下@foo.as_json意願調用包括bar_name喜歡你明顯的例子一樣。

醜陋不建議,但你可以改變檢查foo例如#<Foo id: "abc123", bar_name: "baz">如下

class Foo 
    def inspect 
    base_string = "#<#{self.class.name}:#{self.object_id} " 
    fields = self.attributes.map {|k,v| "#{k}: #{v.inspect}"} 
    fields << "bar_name: #{self.bar_name.inspect}" 
    base_string << fields.join(", ") << ">" 
    end 
end 

那麼「檢查符號」將顯示信息,雖然我還不清楚,如果這是你的意圖,如果是的話,爲什麼你會想這樣。

+0

是的,這實際上解決了我在問題結束時提到的真實案例。有人實際上已經發布了該解決方案,然後將其刪除。但是我仍然想知道是否可以在單次調用之前進行渲染。 @ mmichael似乎已經證實它不是。 –

+1

你是什麼意思「呈現之前」,如果你想在它的對象符號,你將不得不重新定義'檢查' – engineersmnky

+0

我想我已經瞭解到,無論我在控制檯,視圖,或接收JSON,包含虛擬屬性純粹是一種表象問題。否則,當我可以進行方法調用時,「自動」將它包含在返回值中沒有意義。所以正確的答案就像是,「是的,這是可能的,但是當我需要的是重寫'as_json'時,不值得做。謝謝。 –

0

你可以使用attr_accessor - 每Rails docs

定義命名的屬性,這個模塊,其中名稱是symbol.id2name,創建一個實例變量(@name)和相應的訪問方法來讀取它。還創建一個名爲name =的方法來設置屬性。

+0

謝謝,但是當''attr_reader''檢索到對象時,似乎並沒有自動包含虛擬屬性。我純粹問我是否可以在不明確調用該方法的情況下獲取該控制檯輸出。 –

+1

不可能在沒有調用方法的情況下包含虛擬屬性。還有'model.instance_methods',但這只是一個稍微不明顯的調用。缺乏猴子補丁Rails的內置'attr_accessor',恐怕你將不得不調用這個方法。 – mmichael

相關問題