如何Rails的ActiveRecord的关系助手允许的方法,如`user.groups.new`?

2019-07-30 15:25发布

在Rails中,我创建了从LDAP数据库,而不是从ActiveRecord的用户检索模型。 现在,我试图我的ActiveRecord模型与基于LDAP的模型集成,所以我写在我的模型,模拟了一些常见的ActiveRecord方法的方法。

其中一个我试图仿效的方法是通常由通过的has_many上ActiveRecord的关系创建一个。 在ActiveRecord的,这种关系将允许下列:

user = User.first
groups = user.groups # == Array of Groups
groups << Group.create(name: "Test") # How does Rails allow this?

究竟怎样的Rails允许这样做? 我试着动态分配方法由user.groups返回的数组实例,但似乎没有什么办法,使这些用户记录知道将阵列从创建的那些方法。 (所以他们可以分配user_id上的新关系的记录。)我在想什么?

Answer 1:

虽然user.groups似乎是组阵列,它实际上是一个完全独立的类-一个Rails内部类,你平时不很了解称为关联代理。 代理响应类似方法<<createnew的请求代理到目标类,然后相应地设置团体等。

如果你想类似的功能,你必须实现自己的一种代理协会。 这样做将是非常复杂的,但是这可能让你开始。

module LDAP
  class Association
    attr_accessor :source, :target

    def initialize(source, target)
      @source = source
      @target = target
    end

    def <<(obj)
      @source.group_ids = [group_ids + obj].flatten.uniq
      @source.save
    end

  end
end

class User
  def groups
    LDAP::Association.new(self, Group)
  end
end

这甚至不是特别接近的ActiveRecord如何实现关联代理。 然而,这是不是ActiveRecord的解决方案要简单一些,应该是足够的复制一些基本的ActiveRecord功能。



Answer 2:

我会去偷看通过进入Rails的源代码这样做,例如用于Group.create上面的例子中可以找到的代码

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

  def create(attributes = nil, options = {}, &block)
    if attributes.is_a?(Array)
      attributes.collect { |attr| create(attr, options, &block) }
    else
      object = new(attributes, options, &block)
      object.save
      object
    end
  end
end


文章来源: How do Rails ActiveRecord relationship helpers allow methods such as `user.groups.new`?