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

时间:2018-05-18 00:25:06

标签: ruby-on-rails ruby will-paginate

还在学习如何重构我的一些控制器,并希望得到一些建议(我在代码块中留下了一些关于发生了什么的注释)。

我目前的实施工作正常,但我想知道是否有更好的&更容易接近这个;关于在方法中添加这么多实例变量以实现这样一个微不足道的事情。

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

2 个答案:

答案 0 :(得分:1)

您可以使用rails功能单表继承(STI)。这使您可以在一个表中存储类似的模型,因此您可以将常规作业和提取的作业存储在一个表中。选择和分页现在非常简单,并且消除了ruby中任何自定义逻辑的所有需求。这也可能会显着提高您的性能(取决于数据库记录的数量)。

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

所以你要创建父类:

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

此AR的表格必须具有列type(字符串)。

然后从父类派生两种作业类型:

class InternalJob < Job
  # InternalJob related logic
end

class FetchedJob < Job
  # FetchedJob related logic
end

现在,您可以将所有工作提取到您的心中并在其上分页:

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

分页和排序很容易:

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

这可以很好地扩展,因为数据库会进行所有过滤和排序。

这也使您的控制器代码非常小:

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

答案 1 :(得分:0)

您可以尝试以下方法来清理代码

  1. 转到ActiveJob以获取背景中的记录
  2. 使用ActiveSupport :: Concern将控制器的辅助方法保存在另一个文件中。 http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
  3. 或者您可以使用活动作业保存cron作业并以json格式存储结果