Rails:如何限制has_many关联中的项目数(来自Parent)

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)

这是Rails.如果我必须努力工作,我可能做错了什么.

要做到这一点,我必须更新父模型,孩子的控制器,我不能遵循惯例?我错过了什么吗?我在滥用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 << existing_thing` (3认同)

Mat*_*lly 6

保存完成后,验证当前计数会导致计数大于限制.我发现阻止创建发生的唯一方法是在创建之前验证事物的数量小于限制.

这并不是说对用户模型中的计数进行验证是没有用的,但这样做并不会阻止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)


twm*_*lls 0

您如何使用accepts_nested_attributes_for进行调查?

接受嵌套属性:事物,:限制=> 5

http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

也就是说,我认为accepts_nested_attributes_for似乎只适合某些类型的情况。例如,如果您正在创建一个命令行 API,我认为这是一个非常糟糕的解决方案。但是,如果您有嵌套表单,它就足够好了(大多数时候)。