2010-12-02 25 views
0

Dans mon application rails, j'ai 2 modèles: post et post_translations.Rails: colonne limite enum pour les valeurs déjà soumises

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 

Je veux éviter que la même traduction d'être soumis deux fois, donc je veux limiter les énumérations aux valeurs qui ne figurent pas dans la colonne de la langue d'un post_id particulier.
Je ne sais pas si je devrais le faire en modèle, contrôleur ou assistant.
Quelle est la meilleure pratique?

Merci d'avance.

Répondre

1

J'utiliserais un attribut sur la classe au lieu de le définir sur une instance.

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 

Maintenant, pour répondre à vos besoins de montrer que les langues sans traduction, définir une méthode sur le Post:

class Post < ActiveRecord::Base 
    has_many :post_translations 

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

Ensuite, vous pouvez construire un menu de sélection en obtenant un poste (@post = Post.find(params[:id]) et alimenter la collection de @post.untranslated.

+0

ouah! cela marche! – pasine

0

Il est parfaitement valide de garder cela dans le modèle. Les modèles devraient avoir la responsabilité principale de s'assurer que les données qu'ils contiennent sont correctes.

Dans votre cas particulier, vous pouvez utiliser le validateur :uniqueness avec une portée qui lui est transmise. Fondamentalement, votre validation veillera à ce que les langues sont uniques dans le cadre d'un poste particulier

Ce qui suit devrait fonctionner:

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

Si vous préférez les Rails 2 syntaxe de style, vous pouvez utiliser:

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

ok, cela empêchera l'enregistrement de l'enregistrement, mais dans ma liste de sélection je peux toujours choisir toutes les langues: comment puis-je cacher les langues déjà soumises? – pasine

+0

Je pense que cela a besoin d'un nom de colonne, donc ': scope =>: post_id' – zetetic

+0

notme, je pense que vous pourriez probablement faire quelque chose dans un assistant comme' LANGUAGES - @ post.post_translations.all.map {| pt | pt.langue} '. –