简体   繁体   English

Rails:清理控制器中的大型方法

[英]Rails: Cleaning up large methods in controllers

Still learning how to refactor some of my controllers and would like some advice (I left some notes in the code block as to what's going on). 还在学习如何重构我的一些控制器,并希望得到一些建议(我在代码块中留下了一些关于发生了什么的注释)。

My current implementation works OK, but I'm wondering if there is a better & easier way to approach this; 我当前的实现工作正常,但我想知道是否有更好,更简单的方法来解决这个问题; something about adding this many instance variables in the method to pull off such a trivial thing. 关于在方法中添加这么多实例变量以实现这样一个微不足道的事情。

class JobsController < ApplicationController

  def index
    ## records created through app that have been approved (published)
    @paid_jobs = Job.published

    ## records fetched from RSS feed
    @fetched_jobs = JobEntry.all

    ## creates an array of paid_jobs and fetched_jobs, and what is considered the 'feed'. would usually be order("published_at DESC") but you can't call order on an array
    @job = (@paid_jobs + @fetched_jobs).sort_by(&:published_at).reverse

    ## you can't show pagination links for a static array directly. you can, however, first paginate it
    @jobs = @job.paginate(:page => params[:page], :per_page => 10)

    ## this is the actual variable I call in the Job#index view lol
    @published_jobs = @jobs.group_by { |job| job.published_at.to_date }
  end

You could use the rails feature single table inheritance (STI). 您可以使用rails功能单表继承(STI)。 This lets you store similar models in one table,so you could store the regular jobs and the fetched job in one table. 这使您可以在一个表中存储类似的模型,因此您可以将常规作业和提取的作业存储在一个表中。 Selection and pagination would now be very simple and removes all needs for any custom logic in ruby. 选择和分页现在非常简单,并且消除了ruby中任何自定义逻辑的所有需求。 This might also speed up your performance significantly (depending on the number of database records). 这也可能会显着提高您的性能(取决于数据库记录的数量)。

See the official docs: http://guides.rubyonrails.org/association_basics.html#single-table-inheritance 请参阅官方文档: http//guides.rubyonrails.org/association_basics.html#single-table-inheritance

So you would create the parent class: 所以你要创建父类:

class Job < ActiveRecord::Base
  scope :published, -> { where(published: true) } # is inherited by all children
  scope :latest, -> { order(published_at: :desc) } # shortcut for ordering
  # you can add more scopes to enhance readability in controller

  # Job related logic inherited by all children
end

It is important that the table for this AR has the column type (string). 重要的是,此AR的表具有列type (字符串)。

Then you derive both job types from that parent class: 然后从该父类派生两种作业类型:

class InternalJob < Job
  # InternalJob related logic
end

class FetchedJob < Job
  # FetchedJob related logic
end

Now you can fetch all the jobs to your hearts desire and paginate on it: 现在,您可以将所有工作提取到您的心中,并在其上分页:

InternalJob.published # returns all published internal Jobs
FetchedJob.published # returns all published internal Jobs
Job.published # returns all Jobs

pagination and sorting is easy: 分页和排序很容易:

Job.published.sort_by(&:published_at).reverse.paginate(:page => params[:page], :per_page => 10)

This would scale very well as the database does all the filtering and sorting. 当数据库进行所有过滤和排序时,这可以很好地扩展。

This also makes your controller code very slim: 这也使您的控制器代码非常小:

def index
  @published_jobs = Job.published.latest.paginate(:page => params[:page], :per_page => 10).group_by do |job|
    job.published_at.to_date
  end
end

You can try below methods to clean your code 您可以尝试以下方法来清理代码

  1. Go for ActiveJob for fetching the records in background 转到ActiveJob以在后台获取记录
  2. Use ActiveSupport::Concern to keep helper methods for controller in another file. 使用ActiveSupport :: Concern将控制器的辅助方法保存在另一个文件中。 http://api.rubyonrails.org/classes/ActiveSupport/Concern.html http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
  3. Or you can keep cron job using Active Job and store result in json format 或者您可以使用Active Job保留cron作业并以json格式存储结果

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

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