我正试图以优雅的方式解决问题。
我有一个班级:
class Pages < ActiveRecord::Base
# Relations
has_many :contents
has_many :videos
has_many :galleries
has_many :surveys
has_many :documents
end
我想创建一个像这样的哈希
{"videos"=>{:resource_type=>"Video", :resource_id=>2, :resource_name=>"Video di prova"}, "documents"=>{}, "contents"=>{}, "surveys"=>{}, "galleries"=>{}}
收集我的协会中的记录。
我写了一个方法
def get_page_resources
result = {}
['videos','galleries','documents','surveys','contents'].each do |r|
if self.try(r)
res_collection = {}
self.send(r).each do |resource|
res_collection.merge!(resource_type: resource.class.name)
res_collection.merge!(resource_id: resource.id)
res_collection.merge!(resource_name: resource.name)
end
result[r] = res_collection
end
end
return result
end
它有效,但我觉得它很难看。 有没有更好的方法来编写这种方法?
答案 0 :(得分:4)
我会将您的代码重构为以下内容,我认为这些代码具有相当的可读性:
def resources
%w(videos galleries documents surveys contents).map do |name|
[
name, send(name).map do |resource|
{
resource_type: resource.class.name,
resource_id: resource.id,
resource_name: resource.name
}
end
]
end.to_h
end
get_
的方法不是惯用的Ruby。只需在返回之后命名方法即可。 “page”也不需要在名称中,因为这是Pages
上的方法。 (顺便说一下,ActiveRecord模型以单数形式而不是复数形式命名更常见。)%w()
比常规引用词语更好一些。r
不是读者友好的变量名称。我使用name
,意思是“资源名称”,因为从上下文中可以明显看出它是资源的名称。map
或each_with_object
创建可枚举的模式,通过迭代另一个可枚举,然后返回它来构建它,通常可以更清晰,更短。map
对[key, value]
对数组通常很方便,然后将其转换为.to_h
哈希值。try(r)
没有做任何事情,因为关联方法总是返回一个真值。我删除了它。self.
不是必需的。merge!
只能替换为哈希文字。return
在方法结束时是不必要的,而不是惯用的。重构很有趣,所以我按照说明回答了你的问题,但我同意Nermin看起来你可能想要查看序列化框架。
答案 1 :(得分:2)
如何使用序列化程序,它们就是为了做这种工作。
检查以下链接:
答案 2 :(得分:1)
你可以通过将res_collection事物解压缩成这样的方法来清理它:
def get_page_resources
{
videos: res_collection(:videos),
galleries: res_collection(:galleries),
documents: res_collection(:documents),
surveys: res_collection(:surveys),
contents: res_collection(:contents)
}
end
private
# this probably doesn't do what it was supposed to, but
# just to give an impression without digging further into your
# code..
def resource_collection(resource)
res_collection = {}
self.send(resource).each do |resource|
res_collection.merge!(resource_type: resource.class.name)
res_collection.merge!(resource_id: resource.id)
res_collection.merge!(resource_name: resource.name)
end
res_collection
end