什么是Rails 4处理过滤器的方法?

时间:2016-02-19 12:53:51

标签: ruby-on-rails ruby-on-rails-4 filter

背景:我有一些过滤器必须通过系统上的每个CRUD页面提供:搜索,livesearch,列排序和分页;

这就是我目前所拥有的:

.lib/record_filters.rb 
 module RecordFilters

 @@valid_directions = %w[asc desc]

 def search_for(record)
   record.present? ? where('name LIKE ?', record+"%") : all
 end

 def records_matching(search_term)
   where('name LIKE ?', search_term+"%").map(&:name)
 end

 def order_records_by(attribute, direction)
   order(sort_table_by(attribute) +" "+ sort_records_order_by(direction))
 end

 private

 def sort_table_by(attribute)
   column_names.include?(attribute) ? attribute : "name"
 end

 def sort_records_order_by(direction)
   @@valid_directions.include?(direction) ? direction : "asc"
 end

end

./app/models/ticket_type.rb
class TicketType < ActiveRecord::Base
  include RecordFilters 

  validates_presence_of :name
  validates_uniqueness_of :name  

end

./app/controllers/ticket_types_controller.rb
class TicketTypesController < ApplicationController
  before_action :set_ticket_type, only: [:show, :edit, :update, :destroy]

  def index
    @ticket_types = TicketType.search_for(params[:search]).order_records_by(params[:sort], params[:direction]).paginate(per_page: 12, page: params[:page])
    respond_to do |format|
      format.html
      format.js
      format.json { render json: TicketType.records_matching(params[:term]) }
     end
   end
   ...
end

./config/application.rb
...
config.autoload_paths << "#{Rails.root}/lib"

问题:在浏览器上访问索引时,Rails为search_for返回NoMethodError

问题:什么是Rails实现此类过滤器的方法?我做错了什么?

谢谢!

2 个答案:

答案 0 :(得分:2)

这是因为Ruby的include会将模块的方法添加为实例方法

module A
  def value
    5
  end
end
class B
  include A
end
puts B.new.a # prints 5
puts B.a # fails

如果您希望将它们作为类方法,就像类对象本身已扩展一样,请使用extend

method A
  def value
    5
  end
end
class C
  extend A
end
puts C.a # prints 5
puts C.new.a # fails

如果您真的需要include,还可以在模块included回调中定义一些新方法:

module A
  def self.included(mod)
    # mod is whatever (module or class) included A.
    # in this case, it's B.
    mod.class_eval do
      def self.value
        "class"
      end
      # there's no reason to do this here, instead of
      # in the module itself, but just for demonstration purposes:
      def inst
        "inst"
      end
    end
  end
end

class B
  include A
end

puts B.value # prints "class"
puts B.new.inst # prints "inst"

答案 1 :(得分:2)

您的方法已添加为实例方法,但您将其称为类方法,我建议您查看http://api.rubyonrails.org/classes/ActiveSupport/Concern.html以实现模型的关注模式。