何时何地在RESTful Rails API中汇总或执行数据计算

时间:2019-06-24 22:31:02

标签: ruby-on-rails ruby

我想知道在Rails或MVC中,是否存在一种通用的方法来汇总数据或对其进行计算(例如,抓取电影脚本的十条随机行或将十个产品价格彼此相乘) 。具体来说,我正在尝试在应用程序中执行第一个示例(电影脚本的10行)。

我正在使用Rails 5.2+。到目前为止,我一直在尝试在getRandomLines中创建实例方法ScriptLinesController。但是我不确定是否应该使用show方法并在客户端上聚合数据,还是应该将方法放在模型ScriptLine

我已经使用Postman测试了以下路线,并且该路线有效,但似乎执行该路线的方法错误:

#My routes.rb:
Rails.application.routes.draw do
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html

  get 'script_lines/test', to: 'script_lines#getRandomLines'

end

我的控制器如下:

class ScriptLinesController < ApplicationController
  def index
    render json: ScriptLine.all
  end

  def show
    scriptLine = ScriptLine.find_by(id: params[:id])

    render json: scriptLine
  end

  def getRandomLines
    numLines=rand(0..9)
    nineLines = []
    numLines.times do
      id_num = rand(1..ScriptLine.last.id)
      nineLines << ScriptLine.find_by(id: id_num)
    end

    render json: nineLines[0]
  end
end

我的模型如下:

class ScriptLine < ApplicationRecord
  validates :line_number, presence:true

  belongs_to :script
end

最后,我的架构如下:

  create_table "script_lines", force: :cascade do |t|
    t.string "line_number"
    t.string "line"
    t.bigint "script_id"
    t.index ["script_id"], name: "index_script_lines_on_script_id"
  end

总而言之,在控制器中创建方法并指定到这些方法的路由是以RESTful方式汇总/执行数据计算的正确方法吗?特别是,我想知道是否仅允许使用7条标准RESTful路由,或者您是否可以具有用于处理符合REST原理的数据的临时路由。

这是我的第一个问题,因此,如果问得太多或太含糊,事先表示歉意将对此做出相应的修改。

1 个答案:

答案 0 :(得分:3)

这是一个非常广泛的设计问题,所以我只列出要考虑的一般指针:

  • RESTful Web服务设计的主要组成部分是选择正确的资源,这些资源不需要与数据库中的表直接对应。发明新的资源(通常但现在models/中总是有一个对应的类)是完全适当的,这些资源可以更自然地映射到客户正在寻找的东西。
  • 通常,我建议在服务器端在数据库级别执行聚合(或者即使数据库太慢也可以通过其他数据存储机制,例如预先计算的缓存)
  • 如果您使用的是关系数据库,定义执行聚合(https://www.postgresql.org/docs/11/sql-createview.html)的视图会很有用。然后,您可以创建引用视图的ActiveRecord模型
  • 创建与路由文件中的名称不同的控制器方法通常是不值得的。在您的示例中,我将在random处有一个新动作/script_lines/random,然后是一个控制器方法random
  • 取决于您要实现的真正“ RESTful”程度,您可能需要或可能不需要在可接受定义非标准控制器动作以及GET端点返回的可能或不可接受的代码库中工作像这样的随机结果(这两者都可能破坏REST的严格定义)。请查看此答案:RESTful web service to get random number verb,了解更多背景信息。

就个人而言,如果我不太担心RESTful风格,我会像这样向ScriptLinesController添加一个新动作:

class ScriptLinesController < ApplicationController
  def random
    num_lines = rand(0..9)
    render json: ScriptLine.order("RANDOM()").limit(num_lines)
  end
end

随着时间的推移,random函数变得越来越复杂,我考虑将其移至ScriptLine模型中。如果增加了更多的复杂性,这些复杂性在逻辑上与“随机脚本行的集合”的概念有关,那么我会将代码移到另一个模型中,并创建一个新的控制器。