我正在使用rails构建REST API,并且我有一些接受嵌套和递归JSON的控制器,例如,在/taxonomies/:id.json上执行PUT时,您可以传递类似的内容:
{
"names":[
"brands",
"secondary_brands"
],
"taxonomy_data":{
"some":"data"
},
"terms":[
{
"slug":"apple",
"data":{
"value":"Apple California"
},
"overridable_data":{
"weight":0.5
},
"term_data":{
"description":{
"en":"Apple makes the iPhone"
}
}
},
{
"slug":"microsoft",
"data":{
"value":"Microsoft Inc"
},
"overridable_data":{
"weight":0.5
},
"term_data":{
"description":{
"en":"Microsoft makes windows"
}
},
"children":[
{
"data":{
"value":"Xbox"
},
"overridable_data":{
"weight":0.5
},
"term_data":{
"description":{
"en":"Xbox one is bad"
}
}
}
]
},
{
"slug":"hp",
"data":{
"value":"HP Inc"
},
"overridable_data":{
"weight":0.5
},
"term_data":{
"description":{
"en":"HP makes atomic clocks"
}
}
}
]
}
现在,我在我的模型中添加了以下代码:
class Taxonomy < ActiveRecord::Base
has_many :terms,
-> {order(:id)}
def update_terms(params)
existing_term_ids = terms.map &:id
create_term = lambda do |term_params, parent=nil|
t = terms.find_by(:id => term_params[:id]) if term_params[:id]
t ||= terms.build
t.attributes = term_params.slice(:slug, :data, :overridable_data, :term_data)
t.parent = parent
t.save
existing_term_ids.delete(t.id)
if term_params.has_key?(:children)
term_params[:children].each do |child_params|
create_term.call(child_params, t)
end
end
end
params.each do |term_params|
create_term.call(term_params)
end
terms.where(:id => existing_term_ids).destroy_all
save
end
end
此版本(快速写入测试轨道4)使用切片来过滤参数,因为attr_accessible已消失。
这让我想知道这种代码是应该在模型中还是在控制器中。
答案 0 :(得分:1)
阅读这篇文章:http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
我的意见是,你应该在这种情况下提供服务,例如:
# app/services/recursive_update.rb
class RecursiveUpdate
def initalize(source)
@source = source
end
def update(params)
# your code here
end
def create_term(term_params, parent=nil)
#....
end
def permitted_params
#....
end
def save
@source.save
end
end
在控制器中:
updater = RecurciveUpdate.new @model
updater.update params
update.save