2013-10-29 92 views
0

我试图找出如何做这样的事情:添加到收藏之前保存

event = Event.new 
loc = Location.new 
loc.name = "test" 
loc.save 
event.locations << loc 
event.save! 

凡事件和地点有一个多对多的关系。不过,我不断收到此错误:

ActiveRecord::RecordInvalid: Validation failed: Event locations is invalid 

,如果我先救事件,但我没有在上下文选项,我在我的工作

这里是我的模型也能正常工作。

class Event < ActiveRecord::Base 
    #belongs_to :user 
    has_many :event_locations 
    has_many :locations, :through => :event_locations 

    accepts_nested_attributes_for :locations 
end 

class EventLocation < ActiveRecord::Base 
    belongs_to :event 
    belongs_to :location 

    validates_presence_of :event 
    validates_presence_of :location 

    accepts_nested_attributes_for :location 
end 

class Location < ActiveRecord::Base 
    has_many :event_locations 
    has_many :events, :through => :event_locations 
end 

现在我发现连接模型EventLocation上的验证会导致此问题。

我不应该验证这一点吗?有没有不同的方式呢?

+1

调用'event.locations << loc'会隐式调用'loc'上的'save',所以你不需要事先自己做。但是你可以粘贴你的模型,因为我们需要这些信息来回答你的问题。你有验证失败,但没有看到你的验证,我们不能完全回答 – cpjolicoeur

+0

完成。检查出来 – Rob

+0

想通了!感谢你的想法:)。但是,由于validates_presence_of:事件 validates_presence_of:event_locations中的位置。我不需要这些验证吗? – Rob

回答

1

TL; DR

尝试无论是)

class EventLocation < ActiveRecord::Base 
    belongs_to :event 
    belongs_to :location 

    validates_presence_of :event_id 
    validates_presence_of :location_id 

    accepts_nested_attributes_for :location 
end 

或 - 如果你不需要EventLocation为别的 - B)

class Event < ActiveRecord::Base 
    #belongs_to :user 
    has_and_belongs_to_many :locations 

    accepts_nested_attributes_for :locations 
end 

class Location < ActiveRecord::Base 
    has_and_belongs_to_many :events 
end 

这是怎么回事?

在您的'碰撞'模型EventLocation您验证存在导致您的问题的:location:event

为了理解为什么会发生这种情况以及如何解决这个问题,我们需要首先了解验证系统是如何工作的,以及向-collection添加模型的过程。

验证

在我们validate_presence_of的东西,它告诉模型看的东西,看看它是目前这种特殊情况下。

简化:

validates_presence_of :something 
保存时

,导致

model.save if model.something.present? 

所以这应该被检查正确的事情。

什么:through -collections

由于上述显然行不通预期的方式,我们可以推断,

event.locations << loc 

实际上并没有设置

EventLocation.new(location: loc) 

所以真正可能发生的事情是,“唯一”栏设置的ID如

EventLocation.new(location_id: loc.id) 

这是什么意思?

假设上述内容是正确的,验证id的存在而不是关联对象可能会在这里做到这一点。

为什么要麻烦?

当然,验证通常不是一个坏主意,但在这里可能有替代方案,那就是has_and_belongs_to_many。这些方法有很多魔法,它们装备了模型来处理不需要附加模型的碰撞表。

一般来说,如果你没有真的需要附加任何业务逻辑或附加数据到两个表的碰撞,依靠神奇的内置(habtm)为你做正确的事情,而不是手动完成(并验证)它。