0

我正在使用 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

这个版本(快速写入测试 rails 4)使用 slice 来过滤参数,因为 attr_accessible 已经消失了。

这让我想知道这种代码是否应该在模型或控制器中。

4

1 回答 1

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
于 2013-07-19T20:23:47.477 回答