我有一个 hash 表,结构类似这样:
hash = {
:name => [:username],
:age => [:age],
:girlfriend_count => [:girlfrend => [:count]]
}
想要实现的效果是让程序执行:
user = User.find 1
data = {}
hash.each do |key, value|
# block
end
在 block 内实现下面功能:
data[:name] = user.username
data[:age] = user.age
data[:girlfriend_count] = user.girlfrend.count
不知道如何实现,eval 貌似不太优雅。求解。 谢谢大家
#1 楼 @fresh_fish 不是吧?那这个怎么实现?
data[:girlfriend_count] = user.girlfrend.count
if 'attribute'.end_with?('_count')
'attribute' = 'attribute'.delete('_count')
data['attribute'] = user.send('attribute').send('count')
else
data['attribute'] = user.send('attribute')
end
也比较锉
没有看懂需求。
data
的结构必须跟 hash
保持一致么?为什么不能在使用 data 的地方将 User.find 1
返回的对象直接传进去?反正所有的数据也是从 User 的实例中取得的嘛。
或者
if 'attribute' =~ /(.*)_count$/
data[$1] = user.send($1.to_s).send('count')
else
...
end
我曾经写过的一段代码 https://github.com/ery/showbuilder/blob/master/lib/showbuilder.rb 第 54 行
call_object_methods sale, [:customer, :name]
# same with sale.customer.name
def call_object_methods(object, methods)
unless object
return
end
methods = Array.wrap(methods)
if methods.count == 0
return
end
first_method = methods.first
unless first_method
return
end
unless object.respond_to?(first_method)
return
end
method_result = object.send(first_method)
if methods.count <= 1
return method_result
else
remaining_methods = methods.clone
remaining_methods.shift
return call_object_methods(method_result, remaining_methods)
end
end
https://github.com/intridea/hashie/ 不太懂题目。。。。 但操作哈希表什么的,我喜欢用 mash = Hashie::Mash.new(hash) 我现在的项目就在用
Hash[ hash.map{ |k, v| [k, v =~ /(.*)_count$/ ? user.send($1.to_s).send('count') : user.send(v) ] } ]
不知可行不
如果用 Model 的 delegate
方法去取得 user.girlfrend.count
,然后用你在一楼的 send 实现,我感觉足够简洁,优雅易读容易维护了
User < ActiveRecord::Base
delegate :count, :to => :girlfrend, :prefix => true
end
data[:girlfriend_count] = user.send :girlfrend_count
最讨厌这种需求不清楚的问题了,如果实在不知道怎么描述可以这样描述:给出 input 值和想要得到的 output 值,还有不能使用的方法,和要求使用的方法等。
#11 楼 @fresh_fish #10 楼 @azhao 以下是我实现的方法。谢谢大家的支持~!
def call_object_methods(object, methods)
return nil if object.nil?
return object.send methods[0] if methods[0].is_a? Symbol
methods.each do |method|
method.each do |key, value|
return call_object_methods((object.send key), value)
end
end
end
call_object_methods user, {
:name => [:username],
:age => [:age],
:girlfriend_count => [:girlfrend => [:count]]
}
这么用的吗?
hash = {
:name => [:username],
:age => [:age],
:girlfriend_count => [:girlfrend => [:count]]
}
User.find_each(options) do |user|
user_info = {}
@@user_data_list.each do |key, value|
if value.is_a? Array
user_info[key] = call_object_methods user, value
else
user_info[key] = value
end
end
data << user_info
end