Ransack:如何使用现有范围



将Rails 2应用程序转换为Rails 3,我必须替换GEM SearchLogic。现在,使用Rails 3.2.8与GEM Ransack使用我想构建使用现有范围的搜索表格。示例:

class Post < ActiveRecord::Base
  scope :year, lambda { |year| 
    where("posts.date BETWEEN '#{year}-01-01' AND '#{year}-12-31'") 
  }
end  
据我所知,这可以通过定义自定义Ransacker来实现。可悲的是,我找不到有关此文件的任何文件。我在Post类中尝试了此操作:
ransacker :year, 
          :formatter => proc {|v| 
            year(v)
          }

但这不起作用:

Post.ransack(:year_eq => 2012).result.to_sql
=> TypeError: Cannot visit ActiveRecord::Relation

我尝试了ransacker声明的一些变体,但它们都没有起作用。我需要一些帮助...

更新:上面的范围就是例子。我正在寻找一种使用Ransack中每个现有范围的方法。在Ransack的前身Metasearch中,有一个称为search_methods的功能用于使用范围。Ransack尚未开箱即用。

Ransack在合并https://github.com/activerecord-hackery/ransack/pull/390之后将其支持。您应该声明ransackable_scopes方法以添加Ransack可见的范围。

手册

继续从上一节继续进行搜索,需要在模型类上定义ransackable_scopes的白名单。白名单应该是一系列符号。默认情况下,所有类方法(例如范围)被忽略。示波器将用于匹配真实值,或者如果示波器接受值:

class Employee < ActiveRecord::Base
  scope :activated, ->(boolean = true) { where(active: boolean) }
  scope :salary_gt, ->(amount) { where('salary > ?', amount) }
  # Scopes are just syntactical sugar for class methods, which may also be used:
  def self.hired_since(date)
    where('start_date >= ?', date)
  end
  private
  def self.ransackable_scopes(auth_object = nil)
    if auth_object.try(:admin?)
      # allow admin users access to all three methods
      %i(activated hired_since salary_gt)
    else
      # allow other users to search on `activated` and `hired_since` only
      %i(activated hired_since)
    end
  end
end
Employee.ransack({ activated: true, hired_since: '2013-01-01' })
Employee.ransack({ salary_gt: 100_000 }, { auth_object: current_user })

lansack让我们为此创建自定义谓词,不幸的是,文档为改进的空间提供了核对的空间:>

我也相信您要解决的问题是他们的问题跟踪器。那里有一个很好的讨论:https://github.com/ernie/ransack/issues/34

我写了一个名为siphon的宝石,该宝石可帮助您将参数转换为activerailation范围。将其与Ransack结合可以实现。

您可以在此处阅读完整的说明。同时,这是它的要旨

视图

= form_for @product_search, url: "/admin/products", method: 'GET' do |f|
  = f.label "has_orders"
  = f.select :has_orders, [true, false], include_blank: true
  -#
  -# And the ransack part is right here... 
  -#
  = f.fields_for @product_search.q, as: :q do |ransack|
    = ransack.select :category_id_eq, Category.grouped_options
```

好的,现在params[:product_search]保存范围,params[:product_search][:q]具有Ransack Goodness。现在,我们需要找到一种方法,以将数据分配给表单对象。因此,首先让Productsearch吞噬控制器:

控制器

# products_controller.rb
def index
  @product_search = ProductSearch.new(params[:product_search])
  @products ||= @product_formobject.result.page(params[:page])
end

表单对象

# product_search.rb
class ProductSearch
  include Virtus.model
  include ActiveModel::Model
  # These are Product.scopes for the siphon part
  attribute :has_orders,    Boolean
  attribute :sort_by,       String
  # The q attribute is holding the ransack object
  attr_accessor :q
  def initialize(params = {})
    @params = params || {}
    super
    @q = Product.search( @params.fetch("q") { Hash.new } )
  end
  # siphon takes self since its the formobject
  def siphoned
    Siphon::Base.new(Product.scoped).scope( self )
  end
  # and here we merge everything
  def result
    Product.scoped.merge(q.result).merge(siphoned)
  end
end

相关内容

  • 没有找到相关文章

最新更新