たとえば、レコードが「公開」状態になるときに、プラグインまたは最良の方法で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
[EDIT]または属性の大量のために:
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
他の人と共有するためにプラグインを使用することを唱えてくれる人はどれですか?disable_attributes :author, :content, :comments, :when => :published?
特定の状態になっている場合は、妥当性検査で属性の変更をブロックします。あなたは、バリデーションに直接物事をハードコードすることができます。しかし、私は、ホワイトリスト(状態で変更できる属性のリスト)またはブラックリスト(状態で変更できない属性のリスト)を定義する定数を使用するほうが、少し頑強なアプローチを選択します。
両方のアプローチの例を示します。それぞれのアプローチでは、現在の状態または新しい状態を文字列として返す、状態メソッドがモデル内にあることを前提としています。
ホワイトリスト方式
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
私が投稿した後、私の解決策は本書と本質的に似ていることが分かった。私は私がもっと明示的だと信じていますが、これは宣言的であるため、これも良いことです。 –
EmFi - 応答していただきありがとうございます。これは私のRubyの知識のために少し進んでいますが、単なるアンパサンドを含む2行の行については、これが&&の意味でない限り、何が起こっているのか正確には分かりません - 実際にはこれをテストするエラーが発生しています: & 'for {}:ハッシュ –
&は配列の交差演算子です。 http://ruby-doc.org/core/classes/Array.html#M002212配列Aと配列Bは、両方の配列に共通の要素を返します。 A&B == Aの場合、Aのすべての要素はBに入っています。また、複数回コピーして貼り付けたタイプミスのためにエラーが発生しています。変更のすべてのインスタンスが変更されているはずです。私はこれを反映するためにソリューションを更新しました – EmFi
編集検証エラーで編集しないでくださいどの属性:
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.236で導入されたActiveRecord::Dirty拡張を使用します。
フィードバックFrançoisのおかげで、これはこれを行うための別の素晴らしい方法のように見えます。 –
特定の状態が単に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. ActiveRecord:ネストされたレコード属性によるレコードのフィルタ
- 2. state_machine初期状態を他の属性の条件付きに設定する
- 3. ActiveRecord:特定の属性値を持つレコードは1つだけですか?
- 4. Rails ActiveRecord - 複数の属性で検索
- 5. Rails ActiveRecordストアの動的属性
- 6. ActiveRecordのは、元のレコードの属性と比較され
- 7. ActiveRecordのパターンと競合の状態
- 8. LINQ to NHibernate ActiveRecordの状態
- 9. Tkinter Pythonエントリの状態属性
- 10. Rails/Pundit - 特定のユーザーロールに特定の属性を制限する
- 11. Rails:特定のenum属性を持つカテゴリに属している関連レコードを取得する
- 12. 仮想属性でActiveRecordレコードを取得する方法は?
- 13. Rails - ActiveRecordオブジェクトから特定のレコードのみをフェッチする方法は?
- 14. 子供の特定の属性に従ってActiveRecordインスタンスを注文する
- 15. UIBarButtonItemのタイトルテキスト属性をハイライト状態に設定できません
- 16. Railsサニタイザ:スタイル属性に特定のスタイルを許可する
- 17. 特定のクラスのインスタンスである属性のRails検証
- 18. ActiveRecord属性内のレコードの位置(インデックス)を検索します。
- 19. Rails:フォームに指定したときの更新属性のみ
- 20. 同じレコードの2つの属性を比較するactiverecordクエリをレンダリングする
- 21. Orderby特定の状態のときのASC/DESC
- 22. FactoryGirlはRailsのモデルの時刻属性のスキーマとActiveRecordのモデルを考える
- 23. ActiveRecordモデル属性を設定する
- 24. モジュール性とフレックスビューの状態
- 25. 他の子レコードと共に特定の子レコードを持つ親を探すActiveRecordクエリが必要
- 26. Railsの - 参加モデルでレコードを作成するが、属性
- 27. Rails、特定のマルチパラメータ属性をオプションにしますか?
- 28. Rails:特定の順序で属性を作成する
- 29. システムがロックされた状態のときにPythonでスクリーンショットを撮る
- 30. 特定の状態でブートストラップトグル/スイッチが特定の状態でonChangeイベントを防止する
感謝。多数の属性については、これらのセッターをロックする必要のある属性の配列を渡して上書きするためにクラス評価を行うことができますか? –
正確に。私はclass_evalとして書くべきかどうか議論しましたが、読みやすくするためにそれに反対しました。私は他人のためにそれをタックします。 –