【问题标题】:Where to place logic for parsing data before saving to database in Rails?在将数据保存到 Rails 中的数据库之前,在哪里放置解析数据的逻辑?
【发布时间】:2015-05-17 13:36:37
【问题描述】:

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

我有点不清楚我应该在哪里编写逻辑来解析这些数据并将每个国家的每个相关部分保存在我的数据库中 - 在模型或控制器中?我几乎把它放在我的控制器的根索引中,以便在用户访问时立即开始解析,但我只是感觉这违反了胖模型、瘦控制器的 Rails 惯例。

我们将不胜感激任何和所有的帮助。谢谢!

【问题讨论】:

  • 服务对象。检查互动者和/或剧团宝石。

标签: ruby-on-rails


【解决方案1】:

您完全正确,将所有逻辑放在控制器中会违反瘦控制器。

一种方法是通过模型上的方法来解析来自 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,它是普通的旧 ruby​​ 对象,它们接受输入并完成给定的任务。

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

【讨论】:

    【解决方案2】:

    就我自己而言,我的 Rails 工作已经演变成更多的 MVCS 类型的方法。我尽可能地让我的控制器变得又瘦又轻(对我来说,它们只不过是框架的“交通警察”)。

    如果添加的方法代表模型及其数据或其行为,我也会尝试使我的模型保持同样的轻量级。例如,在具有名字和姓氏属性/字段的User 模型中,我通常添加一个名为name 的方法,该方法连接first 和last。

    如果程序要求超出这些或类似用例,我倾向于使用我存储在/app/services 中的服务。

    至少对我而言,经典的待办事项示例是搜索模型,我很少将其放入模型中。相反,我(当然)在控制器中接收搜索请求,然后将参数和任何其他相关详细信息发送到服务类并让它完成工作。

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

    # app/controllers/some_cleverly_named_controller.rb
    def index 
      @search_results = ClientSearch.call(params)
      # ... 
    end
    
    # app/services/client_search.rb
    class ClientSearch 
      def self.call(params)
        ModelName.where(related_id: params[:related_model_id],  active: params[:status]).order("id #{params[:sort_order]}, model_name.last_name #{params[:sort_order]}").includes(:related_model)
      end 
    end
    

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

    如果有兴趣,请在“Rails Services”上进行网络搜索,那里有大量数据!

    祝你好运!

    【讨论】:

    • 完全!当我提交我的并重新加载页面并看到你的页面时不得不大声笑:)!
    猜你喜欢
    • 1970-01-01
    • 2011-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多