2010-12-02 8 views
0

私のレールアプリでは、postとpost_translationsという2つのモデルがあります。Rails:既に提出された値の列挙を制限する

class PostTranslation < ActiveRecord::Base 
    belongs_to :post 

    LANGUAGES = %w(en fr es de it) 
    validates_inclusion_of :language, :in => LANGUAGES 

end 

class Post < ActiveRecord::Base 
    has_many :post_translations 

end 

私は二度提出されることから、同じ言語の翻訳を阻止したいので、私は特定のpost_idのの言語列に表示されていない値に列挙型を制限したいです。
モデル、コントローラ、またはヘルパーでこれを行うべきかどうかわかりません。
どちらがベストプラクティスですか?

ありがとうございます。

答えて

1

インスタンス上で定義するのではなく、クラスの属性を使用したいと思います。

class PostTranslation < ActiveRecord::Base 
    @@languages = %w(en fr es de it) 
    cattr_reader :languages 

    belongs_to :post 

    validates :language, :inclusion => { :in => @@languages }, 
    :uniqueness => { :scope => :post_id } 
end 

さて、翻訳なしで唯一の言語を示すのあなたの要件を満たすポスト上のメソッドを定義するには、次の

class Post < ActiveRecord::Base 
    has_many :post_translations 

    def untranslated 
    PostTranslation.languages - post_translations.map(&:language) 
    end 
end 

を次にあなたがポスト(@post = Post.find(params[:id])を取得して取り込むことにより、選択メニューを構築することができますコレクションは@post.untranslatedです。

+0

うわー!これは動作します! – pasine

0

これをモデルに保存することは完全に有効です。モデルには、入力されたデータが正しいことを保証するための主な責任がある。

特定のケースでは、:uniquenessバリデーターをスコープで渡すことができます。基本的にはあなたの検証は

次は動作するはずの言語は、特定のポストの文脈で一意であることが保証されます:

validates :language, :inclusion => { :in => LANGUAGES }, 
        :uniqueness => { :scope => :post_id } 

あなたがRailsの2スタイルの構文を好む場合は、使用することができます:

validates_uniqueness_of :language, :scope => :post_id 
+0

これでレコードが保存されなくなりますが、私の選択リストではまだすべての言語を選択できます:すでに送信された言語を非表示にするにはどうすればいいですか? – pasine

+0

これはカラム名が必要だと思うので、 ':scope =>:post_id'と書かれています。 – zetetic

+0

notme、私はあなたがおそらく' LANGUAGES - @ post.post_translations.all.map {| pt | pt.language} '。 –

関連する問題