2013-08-21 141 views
0

我希望能夠創建和編輯模型以及關聯的多對多實體。 相關對象應通過具有附加字段和完整性驗證(例如唯一性或存在性)的模型進行連接。 我想用Rails提供的標準驗證機制來檢查完整性。驗證ActiveRecord中的關聯模型(has_many通過)

一個例子是Post(就像這裏在Stackoverflow上),至少有一個Tag且不超過3個TagsTag不能被分配超過一次到單個Post。 此外,將會訂購標籤(連接表中的priority)。

如果違反任何約束,模型應使用自定義驗證器validates並向Post#errors添加錯誤消息。 編輯時,如果任何驗證失敗(例如,帖子標題被刪除或添加了太多標籤),模型及其與TagTagAssignment)的關係將不會被保存。

實施例模型:

class Post < ActiveRecord::Base 
    has_many :tag_assignments 
    has_many :tags, :through => :tag_assignments 

    validates :title, 
      presence: true 
    validates :content, 
      presence: true 
    validates :number_of_tags 

    def number_of_tags 
    valid = self.tags.count.in? 1..3 
    errors.add('error: 1 <= tag.size <= 3') unless valid 
    valid 
    end 
end 

class Tag < ActiveRecord::Base 
    has_many :tag_assignments 
    has_many :posts, through: :tag_assignment 

    validates :name, 
      presence: true 
end 

class TagAssignment < ActiveRecord::Base 
    belongs_to :user 
    belongs_to :tag 

    validates :tag_id, 
      uniqueness: {scope: :post_id} 
    validates :priority, 
      presence: true, 
      uniqueness: {scope: :tag_id} 
end 

實例:

post = Post.build(title: 'title', content: 'content') 
post.save # false 
post.errors # contains message: 'error: 1 <= tag.size <= 3' 
post.tagger << Tag.first 
post.save # true 
post_id = post.id 

post = Post.find(post_id) 
post.tagger << Tag.all[5..10] 
post.save # false 
      # but tag_assignments were already created 
      # and old TagAssignments were not destroyed 

(在我假定tagger是與集priority構建TagAssignments的方法的示例)

什麼是最好的設計模式來管理habtm關係並從內置驗證系統中受益?

+1

參考這樣的回答:

post = Post.build(title: 'title', content: 'content') post.tag_assignments.build(tag: Tag.first, priority: 1) post.save # true, TagAssignments are persisted here post_id = post.id 

更換舊的分配這仍然沒有解決我的時候還有孤兒的問題。我認爲這是你需要的。 http://stackoverflow.com/questions/18290752/rails-error-message-using-fields-for/18291435#18291435 – Bot

回答

0

我需要的解決方案是使用.build而不是<<

post.tag_assignments = [TagAssignment.new(tag: Tag.first, priority: 1)] # an update on assignments sets user_id = NULL and new assignment is inserted 
post.title = nil 
post.valid? # false, but correct TagAssignments were replaced with new ones 
相關問題