Mat*_*oti 18 activerecord ruby-on-rails callback associations
我想限制关联中的项目数.我想确保用户没有超过X物品.这个问题之前被问过,解决方案在孩子身上有逻辑:
class User < ActiveRecord::Base
has_many :things, :dependent => :destroy
end
class Thing <ActiveRecord::Base
belongs_to :user
validate :thing_count_within_limit, :on => :create
def thing_count_within_limit
if self.user.things(:reload).count >= 5
errors.add(:base, "Exceeded thing limit")
end
end
end
Run Code Online (Sandbox Code Playgroud)
硬编码的"5"是一个问题.我的限制根据父级更改.物品集合知道相对于用户的限制.在我们的例子中,管理员可以调整每个用户的(物联网)限制,因此用户必须限制其收集的物品.我们可以让thing_count_within_limit请求其用户的限制:
if self.user.things(:reload).count >= self.user.thing_limit
Run Code Online (Sandbox Code Playgroud)
但是,这是Thing 的很多用户反省.多次调用用户,特别(:reload)是对我来说是红旗.
我认为has_many :things, :before_add => :limit_things会起作用,但我们必须提出一个例外来阻止链条.这迫使我更新things_controller来处理异常,而不是的Rails约定if valid?或if save.
class User
has_many :things, :before_add => limit_things
private
def limit_things
if things.size >= thing_limit
fail "Limited to #{thing_limit} things")
end
end
end
Run Code Online (Sandbox Code Playgroud)
要做到这一点,我必须更新父模型,孩子的控制器,我不能遵循惯例?我错过了什么吗?我在滥用has_many, :before_add吗?我找了一个例子使用:before_add,但找不到任何.
我考虑过将验证移到用户,但这只发生在用户保存/更新上.我没有看到使用它来阻止添加Thing的方法.
我更喜欢Rails 3的解决方案(如果这个问题很重要).
rbi*_*ock 26
因此,如果您希望为每个用户设置不同的限制,可以将things_limit:integer添加到User中并执行
class User
has_many :things
validates_each :things do |user, attr, value|
user.errors.add attr, "too much things for user" if user.things.size > user.things_limit
end
end
class Thing
belongs_to :user
validates_associated :user, :message => "You have already too much things."
end
Run Code Online (Sandbox Code Playgroud)
使用此代码,您无法将user.things_limit更新为低于他已经获得的所有内容的数字,当然它限制用户通过他的user.things_limit创建内容.
应用示例Rails 4:
https://github.com/senayar/user_things_limit
保存完成后,验证当前计数会导致计数大于限制.我发现阻止创建发生的唯一方法是在创建之前验证事物的数量小于限制.
这并不是说对用户模型中的计数进行验证是没有用的,但这样做并不会阻止User.things.create被调用,因为用户的计数集合在保存新的Thing对象之前有效,然后变为保存后无效.
class User
has_many :things
end
class Thing
belongs_to :user
validate :on => :create do
if user && user.things.length >= thing_limit
errors.add(:user, :too_many_things)
end
end
end
Run Code Online (Sandbox Code Playgroud)
您如何使用accepts_nested_attributes_for进行调查?
接受嵌套属性:事物,:限制=> 5
http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
也就是说,我认为accepts_nested_attributes_for似乎只适合某些类型的情况。例如,如果您正在创建一个命令行 API,我认为这是一个非常糟糕的解决方案。但是,如果您有嵌套表单,它就足够好了(大多数时候)。