简体   繁体   English

何时何地聚合或执行RESTful Rails API中的数据计算

[英]When and where to aggregate or perform calculations on data in RESTful Rails API

I was wondering if there is a general way one should go about aggregating data or performing calculations on it (eg grabbing ten random lines of a movie script, or multiplying ten product prices by each other) in Rails or in MVCs in general. 我想知道在Rails或MVC中是否应该采用一般方式来聚合数据或对其进行计算(例如,抓取电影脚本的十个随机行,或者相互乘以十个产品价格)。 Specifically I'm attempting to do the first example (10 lines of a movie script) in my application. 具体来说,我正在尝试在我的应用程序中执行第一个示例(10行电影脚本)。

I'm using Rails 5.2+. 我正在使用Rails 5.2+。 What I've tried so far is making an instance method getRandomLines in my ScriptLinesController . 到目前为止我尝试过的是在我的ScriptLinesController创建一个实例方法getRandomLines But I'm not sure whether I should instead be using the show method and aggregating the data on the client-side, or if I should put the method in the model ScriptLine 但是我不确定是否应该使用show方法并在客户端聚合数据,或者我是否应该将该方法放在模型ScriptLine

I've tested the following route using Postman and it works, but it seems like the wrong way to go about it: 我已经使用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

My controller looks like this: 我的控制器看起来像这样:

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

My model looks like this: 我的模型看起来像这样:

class ScriptLine < ApplicationRecord
  validates :line_number, presence:true

  belongs_to :script
end

Finally my schema looks like this: 最后我的架构如下所示:

  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

So in sum, is creating methods in the controller and specifying routes to those methods the right way to aggregate/perform calculations on data in a RESTful manner? 总而言之,是在控制器中创建方法并指定这些方法的路由,以正确的方式以RESTful方式聚合/执行数据计算? In particular I'm wondering if the 7 standard RESTful routes are the only routes allowed, or if you can have ad-hoc routes for manipulating data that comply with REST principles. 特别是我想知道7条标准RESTful路由是否是唯一允许的路由,或者是否可以使用ad-hoc路由来操作符合REST原则的数据。

This is my first question, so apologies in advance if it's asking too much or too vague, will modify accordingly. 这是我的第一个问题,如果要求太多或太模糊,请提前道歉,因此会相应修改。

This is a pretty broad design question so I'm just going to give a list of general pointers to think about: 这是一个非常广泛的设计问题,所以我只想给出一个思考的一般指针列表:

  • A major component of RESTful web service design is picking the right resources, which do not need to correspond directly with the tables in your database. RESTful Web服务设计的一个主要组件是选择正确的资源,这些资源不需要直接与数据库中的表对应。 It's totally appropriate to invent new resources (usually but now always with a corresponding class in models/ ) that map more naturally to what the client is looking for. 发明新资源(通常但现在总是在models/具有相应的类)完全适合于更自然地映射到客户端所寻找的内容。
  • In general I'd recommend performing aggregations on the server side at the database level (or via some other data-storage mechanism like a pre-computed cache if even the database is too slow) 一般来说,我建议在数据库级别在服务器端执行聚合(或者通过一些其他数据存储机制,如果数据库太慢,也可以像预先计算的缓存一样)
  • If you're using a relational database, it can be useful to define views that perform the aggregation ( https://www.postgresql.org/docs/11/sql-createview.html ). 如果您正在使用关系数据库,则定义执行聚合的视图( https://www.postgresql.org/docs/11/sql-createview.html )会很有用。 Then you can create an activerecord model that references the view 然后,您可以创建引用该视图的activerecord模型
  • It's generally not worth creating controller methods that are named differently from what's in your routes file. 通常不值得创建与路由文件中的命名不同的控制器方法。 In your example I'd just have a new action random at /script_lines/random and then a controller method random . 在您的例子中,我只希望有一个新的动作random/script_lines/random ,然后控制器方法random
  • Depending on how truly "RESTful" you want to be, you may or may not need be working in a codebase where it's acceptable to define non-standard controller actions and it might or might not be acceptable for a GET endpoint to return random results like this (both of these can break the strict definition of REST). 根据您希望的“RESTful”真实程度,您可能需要或者可能不需要在代码库中工作,可以接受定义非标准控制器操作,GET端点可能会或可能不会接受随机结果,如这(这两者都可以打破REST的严格定义)。 Check out this answer: RESTful web service to get random number verb for some more context. 看看这个答案: RESTful Web服务,以获取更多上下文的随机数动词

Personally, if I wasn't overly concerned with RESTful-ness, I'd add a new action to the ScriptLinesController like this: 就个人而言,如果我并不过分担心RESTful-ness,我会向ScriptLinesController添加一个新动作,如下所示:

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

As the random function got more complicated over time I'd consider moving it to the ScriptLine model. 随着random函数随着时间的推移变得越来越复杂,我会考虑将它移到ScriptLine模型中。 If even more complexity got added that was all logically related to the concept of "Collection of random script lines" I'd move that code out to a separate other model and create a new controller. 如果添加的更复杂性与“随机脚本行集合”的概念在逻辑上相关,我会将该代码移到另一个单独的模型并创建一个新的控制器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM