3

これは Rails/ActiveRecord に関する質問です。

基本的にイベントやパフォーマンスを表現する必要があるモデルがあります。各イベントには多くの属性があります。属性は基本的に「このイベントでは、人物 X が役割 Y を持っていた」のようなものです。

ユーザーがこのデータを編集できるようにする最善の方法は、構造化された形式を期待するフリー テキスト フィールドを提供することであると結論付けました。これをロール stringと呼びます。

singer: Elvis Costello, songwriter: Paul McCartney, ...

自動補完を使用して、役割の名前 (歌手、ソングライターなど) と人の名前の両方を補完します。ロールと人の両方がデータベースに保存されます。

これを実装するために、Event モデルに仮想属性を作成しました。

def role_string
    # assemble a role string from the associations in the model
end

def role_string=(s)
    # parse a string in the above role string format,
    # look up the People and Events mentioned, and update
    # what's in the database
end

これで問題ありません。ロール文字列が適切な形式であり、ロール文字列によって指定された関連付けがすべてチェックアウトされている場合、全体が非常にうまく機能します。

しかし、ロール文字列の形式が正しくない場合はどうなるでしょうか? わかりました、標準の検証と一緒に正規表現を使用して形式を確認できます。

validates_format_of :role_string, :with => /(\w+:\s*\w+)(,\s*\w+:\s*\w+)*/

しかし、ロール文字列によって暗示された関連付けが無効な場合はどうなるでしょうか? たとえば、上記のロール文字列を指定Elvis Costelloし、有効な人物を参照していない場合はどうなりますか?

validates_eachたとえば、属性で使用し:role_stringて関連付けを検索し、指定された名前のいずれかが何にも一致しない場合にエラーをスローできると思いました。

私の質問は 2 つあります。まず、関連付けを検証するには、文字列を解析して検索する必要があるため、このアプローチは好きではありません。これは、関連role_string=付けを実際にデータベース。

第二に、... この仮想属性への割り当てでエラーが発生したことをどのように示しますか?

4

1 に答える 1

3

まず第一に、人物をイベントに誤って帰属させています。代わりに、人の名前の文字列ではなく、人の ID をイベントに渡す必要があります。たとえば、ID が 230404 で名前が「Elvis Costello」の Person が、名前を「Britney Spears」に変更するとどうなるでしょうか。その場合、ID は同じままですが、名前が変更されます。ただし、その人物を参照することはできなくなります。

複数のケースで外部キーが人を参照するように関連付けを設定する必要があります。

has_one :singer, :class_name => "Person", :foreign_key => "singer_id"
has_one :songwriter, :class_name => "Person", :foreign_key => "songwriter_id"

このようにして、さまざまな役割の下で複数の人をイベントに関連付けることができ、人が持つ可能性のある複数の属性を参照できます。例えば:

Event.first.singer.name   # => "Elvis Costello"
Event.first.songwriter.name   # => "Britney Spears"

アソシエーションに使用できる検証 ( validates_associated) や、ID がフォームに存在するかどうか( ) を調べることができますvalidates_presence_of。独自のカスタム検証を作成して、Person が before_save で有効であることを確認することをお勧めします。(未テスト) のようなもの:

def before_save
  unless Person.exists?(self.songwriter_id)
    self.errors.add_to_base("Invalid songwriter. Please try again!")
    return false
  end
end

また、イベントの役割に使用する必要があるユーザーを選択する方法を探していることにも気付きました。フォームのパーシャルでできることは次のとおりです。

select(:event, :singer_id, Person.find(:all).collect {|p| [ p.name, p.id ] }, { :include_blank => 'None' })

お役に立てれば!

于 2008-12-01T15:11:10.823 に答える