2

簡単にするために、単純な has-many-through 関係があると仮定します

class User < ActiveRecord::Base
  has_many :courses, :through => :registrations
end

class Registration < ActiveRecord::Base
  belongs_to :user
  belongs_to :course
end

class Course < ActiveRecord::Base
  has_many :users, :through => :registrations
end

アプリを安全に保ちたいのでattr_accessible、属性をホワイトリストに登録しています。

私の質問は 2 つあります。

  1. フォームを介して新しい登録オブジェクトを作成できるように、ホワイトリスト属性を設定するにはどうすればよいですか ( および を渡し:userます:courseが、これらの外部キーが後で悪意を持って更新されるリスクはありませんか?

  2. belongs_to両方の関連付けが必要であると同時に、入れ子になったフォームで登録オブジェクトを作成できるように検証を設定するにはどうすればよいですか?

4

1 に答える 1

2

最初の質問への回答

:user1 つの解決策は、:course読み取り専用としてマークすることです。

attr_readonly :user_id, :course_id

このようにして、作成時に設定できますが、更新時には設定できません。将来更新可能にしたい場合は、登録モデルに特別なメソッドを作成し、@registration.update_dangerous_stuff(params)より高い権限を持つユーザーがアクセスできるコントローラー アクションでのみこのメソッドを使用できます。update_columnメソッドは、これらのフィールドを変更するために、 の行に沿って何かを使用します。

もう 1 つの方法は、ユーザーとコースを設定するための仮想属性を作成することです。これには、現在ユーザーまたはコースを設定できるかどうかを決定するロジックがあります。これが例です。

attr_accessor :safe_user, :safe_course
attr_accessible :safe_user, :safe_course


before_save :set_user, if: 'user.blank?'
before_save :set_course, if: 'course.blank?'


def set_user
  self.user = safe_user
end

def set_course
  self.course = safe_course
end

したがって、フォームでは and の代わりに and フィールドを使用しsafe_userます。この場合、実際に設定され、それらが空白の場合にのみ設定され、実際にアクセス可能として公開されることはありません。コールバック条件をいじることで、このルールをバイパス可能にすることができます。safe_courseusercourseusercourse

2番目の質問への回答

複雑な形式で一連のデータを送信する場合、このデータのどれが意味を持ち、どれが単なるプレースホルダーであるかを判断する方法を考え出すのはあなた次第です。意味のあるデータが送信されない場合は、登録を作成しないでください。ネストされたフォームに触れたことがない場合とは対照的に、誰かが実際に入力しようとして間違いを犯したことを確認するには、どのフォームフィールドが「十分」であるかを判断する必要があります。それを判断する簡単な方法がない場合、その方法の 1 つは、ネストされたフォームに「この登録を追加」チェックボックスを追加することです。そのチェックボックスがチェックされている場合、作成が試行され、検証が実行されます。その後、javascript を追加してこのチェックボックスを非表示にし、ネストされたフォームのいずれかのフィールドをアクティブにした場合に自動的にチェックすることができます。

バックエンドでこの動作を容易にするために、accepts_nested_attributes_for rails メソッドがあります。たとえば、コースモデルでは次のように言えます。

accepts_nested_attributes_for :registrations,
  reject_if: -> attrs { attrs[:name].blank? }

# Don't forget this too 
attr_accessible :registrations_attributes

Rails にはショートカットも用意されています。

accepts_nested_attributes_for :registrations, reject_if: :all_blank

チェックボックスの場合はreject_if: -> attrs { attrs[:my_check_box] == '1' }、 などと言うことができます。

与えられたprocの条件が満たされない場合、登録を作成して検証するのではなく、登録を単に無視することをreject_ifRailsに伝えます。

これがあなたに遊び心のあるアイデアを与えてくれることを願っています。

于 2012-09-15T06:07:22.247 に答える