在Rails中保存到数据库之前,在哪里放置解析数据的逻辑?

时间:2015-05-17 13:36:38

标签: ruby-on-rails

我正在收集有关世界上所有国家/地区的公开数据,并且需要能够解析该JSON文件,以便为每个国家/地区提取相关内容并将其存储到我的数据库中。

我有点不清楚我应该编写逻辑来解析数据并保存数据库中每个国家/地区的每个相关部分 - 在模型或控制器中?我几乎把它放在我的控制器的根索引中,一旦用户访问就开始解析,但我只是觉得这违背了胖模型,瘦控制器的rails惯例。

非常感谢任何和所有帮助。谢谢!

2 个答案:

答案 0 :(得分:2)

对于我自己来说,我的Rails工作已经演变成更多的MVCS类型方法。我尽可能保持控制器的瘦弱和轻盈(对我来说,他们只不过是#34;交通警察和#34;框架)。

我尝试同样保持我的模型轻松,其中添加的方法代表模型及其数据或其行为。例如,在具有名字和姓氏属性/字段的java.lang.object模型中,我通常会添加一个名为User的方法,该方法首先连接到最后一个。

如果程序要求不属于那些或类似的用例,我倾向于使用我存储在name中的服务。

至少在我看来,经典的,做得很好的例子是搜索模型,我很少将其放在模型中。相反,我在控制器中接收搜索请求(当然),然后将params和任何其他相关细节发送到服务类并让它完成工作。

这是一个非常基本的搜索示例......非常基本:)!

/app/services

我有一个超级简单,但名称很gem that generates a service和一个rspec模板,以防你尝试使用服务方法。

如果有兴趣,请在" Rails服务"上进行网络搜索。并且有丰富的数据!

祝你好运!

答案 1 :(得分:2)

你绝对正确的做法是将所有逻辑放在控制器中会违反瘦小的控制器。

一种方法是通过模型上的方法解析来自api的数据:

class Cat < ActiveRecord::Base
    def self.create_from_kittypix_api(data, &block)
      model = self.new(attrs_from_some_api(data))
      yield(model, data) if block_given?
      model
    end

    def self.attrs_from_kittypix_api(data)
      {
         foo: data[:bar]
      }
    end 
end

这里的缺点是你的模型最终对外部API了解得太多,一次创建几个模型会导致对责任的混淆。

更新的方法是using services,它是普通的旧红宝石对象,它接受输入并完成给定的任务。

class KittypixImportService
  def self.call(kitty_pix_id)
    client = KittyPixClient.new
    result = client.get_kitty(id: kitty_pix_id)
    Cat.new(
      foo: result['bar']
    )
  end
end