想知道是否有插件或設置ActiveRecord類的最佳方式,例如,當記錄進入「已發佈」狀態時,某些屬性被凍結他們不能被篡改。Rails ActiveRecord:記錄進入特定狀態時鎖定屬性
回答
通過將@readonly設置爲true(在方法中),您可以凍結整個AR :: B對象,但會鎖定所有屬性。
我建議的方法是定義屬性setter方法傳遞給超之前檢查當前的狀態:
class Post < ActiveRecord::Base
def author=(author)
super unless self.published?
end
def content=(content)
super unless self.published?
end
end
[編輯]或大量屬性:
class Post < ActiveRecord::Base
%w(author content comments others).each do |method|
class_eval <<-"end_eval", binding, __FILE__, __LINE__
def #{method}=(val)
super unless self.published?
end
end_eval
end
end
當然我會主張拉入插件與他人分享,並添加一個很好的DSL訪問像:disable_attributes :author, :content, :comments, :when => :published?
您可以添加ac如果您處於特定狀態,則使用ustom驗證來阻止對屬性的更改。你可以直接將驗證碼直接寫入代碼。但我更喜歡使用定義白名單的常量(允許在狀態中更改的屬性列表)或黑名單(不允許在狀態中更改的屬性列表)的更穩健的方法。
下面是兩種方法的示例。每種方法都假定模型中有一個狀態方法,以字符串形式返回當前/新狀態。
白名單方法
WhiteListStateLockMap = {
"state_1" => [
"first_attribute_allowed_to_change_in_state_1",
"second_attribute_allowed_to_change_in_state_1",
...
],
"state_2" => [
"first_attribute_allowed_to_change_in_state_2",
"second_attribute_allowed_to_change_in_state_2",
...
],
...
}
validates :state_lock
def state_lock
# ensure that all changed elements are on the white list for this state.
unless changed & WhiteListStateLockMap[state] == changed
# add an error for each changed attribute absent from the white list for this state.
(changed - WhiteListStateLockMap[state]).each do |attr|
errors.add attr, "Locked while #{state}"
end
end
end
黑名單方法
BlackListStateLockMap = {
"state_1" => [
"first_attribute_not_allowed_to_change_in_state_1,
"second_attribute_not_allowed_to_change_in_state_1,
...
],
"state_2" => [
"first_attribute_not_allowed_to_change_in_state_2",
"second_attribute_not_allowed_to_change_in_state_2",
...
],
...
}
validates :state_lock
def state_lock
# ensure that no changed attributes are on the black list for this state.
unless (changed & BlackListStateLockMap[state]).empty?
# add an error for all changed attributes on the black list for this state.
(BlackListStateLockMap[state] & changed).each do |attr|
errors.add attr, "Locked while #{state}"
end
end
end
我發佈後,我意識到我的解決方案基本上與此類似,只是寫法不同。我相信我是更明確的,但這也是好的,因爲它更具說明性。 – 2009-11-19 23:39:24
EmFi - 感謝您的迴應。這對於我的Ruby知識來說有點高級,就涉及單個&符號的兩行代碼而言,我不確定到底發生了什麼,除非這意味着是&& - 實際上我得到了一個測試錯誤:未定義的方法' &'for {}:哈希 – 2009-11-20 05:20:17
&是數組的交集操作符。 http://ruby-doc.org/core/classes/Array.html#M002212。數組A和數組B返回兩個數組通用的元素。如果A&B == A,那麼A的所有元素都在B中。而且由於我的多次複製和粘貼的錯字,您也會收到錯誤。所有更改的實例都應該已經更改。我已經更新瞭解決方案,以反映這 – EmFi 2009-11-20 06:28:14
編輯屬性不應被編輯驗證錯誤:
class Post < ActiveRecord::Base
validate :lock_down_attributes_when_published
private
def lock_down_attributes_when_published
return unless published?
message = "must not change when published"
errors.add(:title, message) if title_changed?
errors.add(:published_at, message) if published_at_changed?
end
end
氏s使用了2.2左右的ActiveRecord::Dirty擴展。
感謝您的反饋François,這看起來是另一個偉大的方式做到這一點。 – 2009-11-20 05:00:00
如果特定狀態只是persisted?
,那麼attr_readonly
是最佳選擇。
attr_readonly
(*attributes)
公共
Attributes listed as readonly will be used to create a new record but update operations will ignore these fields.
爲了測試(的THAiSi提供):
class MyModel < ActiveRecord::Base
attr_readonly :important_type_thingie
end
#RSpec
describe MyModel do
its('class.readonly_attributes') { should include "important_type_thingie" }
it "should not update the thingie" do
m = create :my_model, :important_type_thingie => 'foo'
m.update_attributes :important_type_thingie => 'bar'
m.reload.important_type_thingie.should eql 'foo'
end
end
- 1. Rails ActiveRecord:記錄進入特定狀態時鎖定特定關聯
- 2. rails/ActiveRecord:如何爲特定屬性指定不同的類?
- 3. 在插入記錄時鎖定
- 4. 包含自定義屬性的DLL保持鎖定狀態
- 5. 鎖定記錄
- 6. ActiveRecord自定義屬性
- 7. 禁止Rails日誌記錄特定的ActiveRecord請求
- 8. Rails ActiveRecord如何關閉記錄特定查詢
- 9. 的ActiveRecord ::關聯打印特定屬性
- 10. 使用狀態屬性來維護Rails中的舊記錄
- 11. 記錄時間自定義屬性C#
- 12. 窗口性能記錄器記錄特定進程
- 13. ActiveRecord:確保只有一個記錄具有特定的屬性值?
- 14. 無論鎖定狀態如何,寫入鎖定的文件
- 15. ActiveRecord:通過嵌套記錄屬性篩選記錄
- 16. 檢查是否ActiveRecord的被鎖定在「更新」狀態
- 17. 批處理腳本,在特定時間進入睡眠狀態
- 18. 定時器鎖定屬性爲只讀鎖定功能
- 19. Rails ActiveRecord商店中的動態屬性
- 20. android手機鎖定時的WIFI狀態
- 21. 屏幕鎖定時的狀態欄android
- 22. Rails activerecord查詢比較同一記錄的兩個屬性
- 23. Rails的ActiveRecord的插入記錄結果
- 24. 我何時需要擔心ActiveRecord鎖定?
- 25. oracle帳戶鎖定狀態
- 26. 鎖定狀態不一致
- 27. SharpSvn - 鎖定文件狀態
- 28. ActiveRecord的自定義屬性
- 29. Yii2 activerecord自定義屬性
- 30. ActiveRecord :: DangerousAttributeError - 屬性?由ActiveRecord定義
感謝您的反饋科林。對於大量的屬性,我想我可以通過傳入需要被鎖定的屬性數組來完成一個類的eval來覆蓋這些設置器,呃? – 2009-11-19 20:28:34
準確。我辯論是否應該把它寫成class_eval,但是爲了可讀性而決定不採用它。我會盡力爲別人着想。 – 2009-11-19 20:55:38