1

在 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新的关系记录。)我错过了什么?

4

2 回答 2

2

虽然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 功能。

于 2012-07-26T16:28:50.757 回答
0

我会通过查看 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
于 2012-07-26T16:36:02.807 回答