Rails:清理控制器中的大型方法
Rails: Cleaning up large methods in controllers
仍在学习如何重构我的一些控制器并希望得到一些建议(我在代码块中留下了一些关于正在发生的事情的注释)。
我目前的实现工作正常,但我想知道是否有更好更简单的方法来解决这个问题;关于在方法中添加这么多实例变量以完成如此微不足道的事情。
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
您可以尝试以下方法清理您的代码
- 使用 ActiveJob 在后台获取记录
- 使用ActiveSupport::Concern将控制器的辅助方法保存在另一个文件中。 http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
- 或者您可以使用 Active Job 保留 cron 作业并将结果存储为 json 格式
您可以使用 rails 功能单 table 继承 (STI)。这使您可以将相似的模型存储在一个 table 中,这样您就可以将常规作业和获取的作业存储在一个 table 中。选择和分页现在变得非常简单,并且消除了 ruby 中对任何自定义逻辑的所有需求。这也可能会显着提高您的性能(取决于数据库记录的数量)。
查看官方文档:http://guides.rubyonrails.org/association_basics.html#single-table-inheritance
所以你会创建父 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
重要的是,此 AR 的 table 具有列 type
(字符串)。
然后你从那个父派生两种工作类型 class:
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
仍在学习如何重构我的一些控制器并希望得到一些建议(我在代码块中留下了一些关于正在发生的事情的注释)。
我目前的实现工作正常,但我想知道是否有更好更简单的方法来解决这个问题;关于在方法中添加这么多实例变量以完成如此微不足道的事情。
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
您可以尝试以下方法清理您的代码
- 使用 ActiveJob 在后台获取记录
- 使用ActiveSupport::Concern将控制器的辅助方法保存在另一个文件中。 http://api.rubyonrails.org/classes/ActiveSupport/Concern.html
- 或者您可以使用 Active Job 保留 cron 作业并将结果存储为 json 格式
您可以使用 rails 功能单 table 继承 (STI)。这使您可以将相似的模型存储在一个 table 中,这样您就可以将常规作业和获取的作业存储在一个 table 中。选择和分页现在变得非常简单,并且消除了 ruby 中对任何自定义逻辑的所有需求。这也可能会显着提高您的性能(取决于数据库记录的数量)。
查看官方文档:http://guides.rubyonrails.org/association_basics.html#single-table-inheritance
所以你会创建父 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
重要的是,此 AR 的 table 具有列 type
(字符串)。
然后你从那个父派生两种工作类型 class:
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