如何确保关联的属性是否正确以验证关联?

时间:2011-03-03 20:24:38

标签: ruby-on-rails ruby validation ruby-on-rails-3

我有一个简单的用户:**为了清晰起见而编辑了一下,以及Sam的建议

class User < ActiveRecord::Base
  # <snip other attribs>
  has_many :handles
  has_one :active_handle, :class_name => "Handle"

  validates_each :active_handle, :allow_nil => true  do |record, attr, value|
    record.errors.add attr, "is not owned by the correct user" unless record.handles.include?(value)
  end
end

一个句柄模型:

class Handle < ActiveRecord::Base
  belongs_to :user
  attr_accessible :user_id
  validates :user_id,
        :presence => true,
        :numericality => true

  attr_accessible :name
  validates :name,
        #etc...
end

现在,我想在设置User.active_handle关联时检查句柄是否由正确的Handle.user_id拥有。我试图在自定义验证中执行此操作,也在User模型的验证方法中执行此操作。两种方式,它与我想要的完全相反,它将句柄的user_id设置为用户进行检查。

我已经走到了尽头,很明显我听不懂东西,谷歌也没有把我带到任何我尚未到过的地方。

ETA:我还试图操纵has_one与条件的关联,这似乎也失败了......

has_one :active_handle,
        :class_name => "Handle",
        :conditions => ['user_id =?', '#{self.id}']

2 个答案:

答案 0 :(得分:0)

如果您是从用户模型进行的,那么您需要将验证添加到用户模型而不是句柄模型,因为用户正在更新。

这是我在验证用户实际属于句柄之前如何激活它。

class Handle < ActiveRecord::Base
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :handles
  validates :handle_can_be_active?

  def handle_can_be_active?
      if self.handles.include?(self.active_handle)
          #no problem
      else
          errors.add_to_base('Must belong to the handle before it can be active!')
      end
  end
end

答案 1 :(得分:0)

我会对这个问题采取不同的方法;正如你所发现的那样,双重联系是混乱的,难以维持。相反,我在句柄模型中放置了一个活动标志,并在该标志上排序:active_handle关联:

class User < ActiveRecord::Base
    has_many :handles
    has_one  :active_handle, :class_name => 'Handle', :order => 'handles.active DESC'
end

现在只有一个链接,它与已建立普通has_many :handles关联(即Handle模型中的user_id属性)的链接相同。现在找到活动句柄只是找到用户的第一个Handle并设置了活动标志。我会使用:order而不是:conditions,因为它会给你一个很好的回退:如果没有该用户的句柄设置了活动标志,Rails将选择一个用作默认值

然后,在你的句柄模型中,你可以有一个相当简单的激活函数:

class Handle < ActiveRecord::Base
    # ...stuff...

    def activate!
        # Pseudocode - sorry!
        sql('UPDATE handles SET active = 0 WHERE user_id = ?', self.user_id)
        self.active = true
        self.save!
    end
end

或者,如果您希望能够调用类似user.handles.activate(hdl)的内容,则可以添加类似于关联扩展名的内容。或user.active_handle = hdl。还是......

希望这有帮助!