find_or_initialize_by和has_many:通过

时间:2011-08-01 18:18:06

标签: ruby-on-rails has-many-through

我有一个用户从中导入数据的xml文件。这会在Player模型中创建记录。 同时,我希望在Membership关联中创建一条记录。

如果记录尚不存在,则只应触发上述两种情况。 这是该方法的缩短版本:

@player = self.players.find_or_initialize_by_name_and_archetype(name, archetype)
if @player.save
  self.memberships.create(:player_id => @player.id)
end

现在find_or_initialize_by有效,但仍为每位玩家创建Membership,基本上忽略了if条件。

怎样才能以简洁的方式做到这一点?

2 个答案:

答案 0 :(得分:2)

如果从查找或初始化设置@player,则调用它的保存仍然可以返回true,即使它不是新记录 - 通过查找对象而不是更改任何内容在控制台中尝试在它上面调用save,只要它是一个有效的对象,你仍然会成为现实。

话虽如此,我认为你希望你的条件更符合

if @player.new_record? && @player.save

答案 1 :(得分:1)

恕我直言,更清洁的方法是向成员资格添加唯一性约束我不知道你的代码中有谁selfTeam?)

class Team < ActiveRecord::Base
has_many :memberships, :before_add => :validates_membership

我会默默地删除数据库调用并报告成功。

def validates_membership(membership)
  raise ActiveRecord::Rollback if self.memberships.include? membership
end

ActiveRecord ::回滚是内部捕获但未重新加载 然后,您只需致电self.memberships.create(:player_id => @player.id),就不会创建重复的会员资格 如果您希望可以在数据库级add_index :memberships, [ :team_id, :player_id ], :unique => true, :name => 'by_team_and_player上添加唯一性约束。

而且,最后但并非最不重要(有人会说你应该先做),你可以添加测试来验证成员资格的唯一性。