我有两个对象, UserData 对象和用户对象。目前他们看起来像这样:
user_data.rb
class UserData < ActiveRecord::Base
self.table = "users"
end
user.rb
class User
attr_accessor :first_name, :last_name, :email, :password
end
我现在要做的是将 UserData 对象映射到用户对象,反之亦然。对于第一个场景,我有以下代码:
module Mappers
module UserMapper
def map user
@user = UserData.new
@user.first_name = user.first_name
@user.last_name = user.last_name
@user.password = user.password
@user.email = user.email
end
end
end
然而,问题是每当我向users表添加一个新列时,我也必须在mapper中添加代码。当我的代码中有大量的对象需要映射时,它会变得非常混乱。我的问题是:这样做有更好/更好的方式吗?理想的情况是我不再需要触摸Mapper代码了。
答案 0 :(得分:2)
你可以使用一点ruby元编程来完成这个:
class User
ATTRS = [:first_name, :last_name, :email, :password]
attr_accessor *ATTRS
end
module Mappers
module UserMapper
def map(user)
@user = UserData.new
User::ATTRS.each do |attr|
@user.send("#{attr}=", user.send(attr))
end
end
end
end
然后你只需修改ATTRS
,一切都会自动生效!
答案 1 :(得分:2)
您可以通过调用attribute_names
类方法从ActiveRecord模型中获取属性名称列表。有了它,可以很容易地迭代它们并依次获取和分配每个属性:
module UserMapper
def map(user)
@user = UserData.new do |user_data|
UserData.attribute_names.each do |attr_name|
next unless user.respond_to?(attr_name)
user_data[attr_name] = user.public_send(attr_name)
end
end
end
end
如果您愿意,可以使用相同的方法在User类中动态创建attr_accessor
:
class User
attr_accessor *UserData.attribute_names
end
答案 2 :(得分:1)
您可以根据此问题执行某些操作:Fastest/One-liner way to list attr_accessors in Ruby?
module Mappers
module UserMapper
def map user
@user = UserData.new
user.attributes.inspect.each do |attr|
@user.public_send("#{attr}=", user.public_send(attr))
end
end
end
end