1

attr_accessible將所有非指定屬性標記爲受保護的,但我仍需要在create上寫入一些關鍵屬性,如attr_readonly所支持。使用attr_accessible和attr_readonly不允許創建記錄

我有我的模式設置,如下所示:

class Foo < ActiveRecord::Base 
    attr_accessible :bar, :baz 
    attr_readonly :shiz 
end 

class FooParent < ActiveRecord::Base 
    has_many :foos 
end 

@foo_parent.foos.build(:bar => 1, :baz => 2, :shiz => 3)  # Can't mass-assign protected attribute: :shiz 

明顯的解決方法在這裏是不使用attr_readonly,在密鑰的屬性創建對象,然後設置並保存之後。這種方法的缺點是我現在至少有2次寫入,而且這種創建方法需要像人類一樣可以保持高性能。

@foo_parent.foos.build(:bar => 1, :baz => 2)     # write #1 
@foo_parent.foos.each do |f| 
    f.update_attribute(:baz, 3)        # write #2 and more 
end 

我怎樣才能實現與訪問屬性的對象的創建和1個寫入只讀屬性,而不會觸發Can't mass-assign protected attributes錯誤,同時,還能享受創建後只讀保護帶來的好處?

+0

可能這是你想要的http://stackoverflow.com/questions/5937702/how-can-i-overwrite-attr-readonly –

+0

沒有,attr_protected是不是我想要的,因爲我_DO_要質量 - 在創建時分配只讀變量。 – coneybeare

+0

「寫入#1」,「不寫入」,「寫入1」。我不明白這些評論意味着什麼。 – Nowaker

回答

3

您可以用Foo.new替代Foo.create

f = Foo.new(:bar => 1, :baz => 2)    # no write 
f.update_attribute(:shiz, 3)      # write 1 

您還可以設置:shizattr_accessibleattr_readonly

attr_accessible :bar, :baz, :shiz 
attr_readonly :shiz 

f = Foo.create(bar: 1, baz: 2, shiz: 3)  # write 1 

如果現在嘗試修改:shiz它不會改變(因爲它是隻讀):

f.update_attribute(:shiz, 15) 
f.reload 
f.shiz 
=> 3 
+0

因此,代碼實際上使用.build已在一行,然後保存。我剛剛在這裏提到創建可讀性。將shiz設置爲可訪問和只讀都不起作用。我能夠在創建完成後對shiz應用更新,而不會像預期的那樣獲得批量分配錯誤。 – coneybeare

+0

我編輯了問題中的示例以顯示我已經在使用構建。當構建被用作has_many關聯的一部分時,它在調用期間寫入 – coneybeare

+0

@coneybeare:這是不正確的 - 雖然':shiz'可以使用批量賦值傳遞給'update_attributes'而不會出錯,因爲它是隻讀的,因此在創建後會產生效果。實際上,'attr_readonly'不是設計用來拋出錯誤。它只是從任何UPDATE語句中過濾出這些屬性,使其有效地只讀。在模型級別,爲此拋出錯誤的唯一方法是使用驗證器。查看已更新。 – PinnyM

4

編輯:看到Mass assignment security

更換

attr_accessible :bar, :baz 

attr_accessible :bar, :baz, :shiz 
+0

將shiz設置爲可訪問和只讀都不起作用。我能夠在創建完成後對shiz應用更新,而不會像預期的那樣獲得批量分配錯誤。 – coneybeare

+0

我是不正確的,請在這裏看到評論http://stackoverflow.com/a/14721213/69634 - 不幸的是,我不能扭轉你的downvote,除非你編輯你的答案,所以請編輯它,所以我可以添加upvote代替。 – coneybeare

+0

謝謝@coneybeare。更新了答案 – shweta