Ruby on rails 在添加关联回调之前以静默方式跳过添加,而不是引发异常?
我正试着这么做Ruby on rails 在添加关联回调之前以静默方式跳过添加,而不是引发异常?,ruby-on-rails,activerecord,callback,Ruby On Rails,Activerecord,Callback,我正试着这么做 has_many :roles, :before_add => :enforce_unique def enforce_unique(assoc) false if exists? assoc end 文档中写道:“如果before_add回调引发异常,则该对象不会添加到集合中”。上面的使用false并不能阻止添加,因此我不得不这样做: def enforce_unique(assoc) raise if exists? assoc end 这样
has_many :roles, :before_add => :enforce_unique
def enforce_unique(assoc)
false if exists? assoc
end
文档中写道:“如果before_add回调引发异常,则该对象不会添加到集合中”。上面的使用false并不能阻止添加,因此我不得不这样做:
def enforce_unique(assoc)
raise if exists? assoc
end
这样,它确实不会被添加,但它也会引发一个必须处理的异常。在这里对我不是很有用。我希望它的行为更像保存前的常规AR回调,返回FALSE也可以防止保存(或添加),但不会引发异常
在上面的这种情况下,我宁愿这样做,也不要默默地添加assoc。有办法做到这一点吗?我错过了什么?或者引发异常是这里唯一的选项吗?如果关联不是多态的,您可以执行以下操作:
validates_uniqueness_of :name_of_model
这个问题有点老了,但我最近遇到了同样的问题。我是这样解决的:
def enforce_unique |obj, x|
v = obj.roles
if i = v.index(x)
v.slice! i
end
end
我认为解决这个问题的方法是使用
throw
和catch
,它们在Ruby中用于流控制。提出异常并不合适,因为这不是异常情况
我最后做了:
catch(:duplicate) do
association.create({})
end
然后在添加之前的回调中,我做了:
if(Class.where({}).first)
throw :duplicate
end
更多关于投掷/接球的信息,请点击此处:
由于此问题是关于保存而不是临时阻止它被包括在列表中(例如由一个对控制其模型不感兴趣的控制器),您可以尝试覆盖相关模型中的保存,如果角色存在,则不保存它:
class Role < ActiveRecord::Base
belongs_to :user, inverse_of: :roles
def save
super unless self.new_record? && user.has_existing_role?(self)
end
end
类角色
旁注:当与活动记录模式一起使用时,我不相信skinny controller参数,因为业务逻辑必须放在某个地方。对于像activerecord这样的业务领域糟糕的模式(不具体指Ruby AR gem),它确实需要在上面存在一层(即控制器层),您可以使用服务对象或装饰器模式作为实现这一点的手段
另一种方法是覆盖更新方法,如