繁体   English   中英

动态地包含Rails中对象的关联

[英]Dynamically include associations for objects in Rails

我目前正在开发一个小型的Rails 5应用程序,我需要根据某些事件将ActiveRecord对象传递给外部服务。 在我的模型中,我定义了以下内容:

# /models/user.rb
after_create :notify_external_service_of_user_creation

def notify_external_service_of_user_creation
  EventHandler.new(
    event_kind: :create_user,
    content: self
  )
end

然后, EventHandler将此对象转换为JSON,并通过HTTP请求将其发送到外部服务。 通过在对象上调用.to_json ,这将呈现一个JSON输出,如下所示:

{
  "id":1234,
  "email":"test@testemail.dk",
  "first_name":"Thomas",
  "last_name":"Anderson",
  "association_id":12,
  "another_association_id":356
}

现在,我需要一种方法将所有第一级关联直接包含在其中,而不是仅显示foreign_key。 所以我正在寻找的构造将是这样的:

{
  "id":1234,
  "email":"test@testemail.dk",
  "first_name":"Thomas",
  "last_name":"Anderson",
  "association_id":{
    "attr1":"some_data",
    "attr2":"another_value"
  },
  "another_association_id":{
    "attr1":"some_data",
    "attr2":"another_value"
  },
}

我的第一个想法是如此反思模型: object.class.name.constantize.reflect_on_all_associations.map(&:name) ,其中object是这种情况下用户的实例,并使用此列表循环关联并将它们包含在输出中。 这似乎相当乏味,所以我想知道是否有更好的方法来实现这个使用Ruby 2.4和Rails 5。

如果您不想使用外部序列化程序, as_json以为每个模型覆盖as_json as_json得到由称为to_json

module JsonWithAssociations
  def as_json
    json_hash = super

    self.class.reflect_on_all_associations.map(&:name).each do |assoc_name|
      assoc_hash = if send(assoc_name).respond_to?(:first)
                     send(assoc_name).try(:map, &:as_json) || [] 
                   else
                     send(assoc_name).as_json 
                   end

      json_hash.merge!(assoc_name.to_s => assoc_hash)
    end 

    json_hash
  end
end

您需要prepend此特定模块,以便它覆盖默认的as_json方法。

User.prepend(JsonWithAssociations)

要么

class User
  prepend JsonWithAssociations
end

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM