背景:我有一些过滤器必须通过系统上的每个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实现此类过滤器的方法?我做错了什么?
谢谢!
答案 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以实现模型的关注模式。