Ransack: Как использовать существующий прицел?

Преобразуя приложение Rails 2 в Rails 3, я должен заменить гемsearchlogic, Теперь, используя Rails 3.2.8 с гемомразграбить Я хочу построить форму поиска, которая использует существующую область видимости. Пример:

class Post < ActiveRecord::Base
  scope :year, lambda { |year| 
    where("posts.date BETWEEN '#{year}-01-01' AND '#{year}-12-31'") 
  }
end  

Насколько я знаю, это может быть достигнуто путем определения обычаяграбитель, К сожалению, я нене найти никакой документации по этому поводу. Я попробовал это вPostучебный класс:

ransacker :year, 
          :formatter => proc {|v| 
            year(v)
          }

Но это не работает

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

Я попробовал некоторые вариантыransacker декларация, но ни одна из них не работает. Мне нужна помощь...

ОБНОВИТЬ: Объем выше только на примере. Я'Я ищу способ использовать каждую существующую область в Ransack. В MetaSearch, предшественнике Ransack, есть функция, которая называетсяsearch_methods для использования областей. Ransack имеетнет поддержки для этого из коробки еще.

Ответы на вопрос(3)

Ransack let 'Если вы создаете пользовательские предикаты для этого, к сожалению, документация оставляет место для улучшения, однако извлечение:https://github.com/ernie/ransack/wiki/Custom-Predicates

Также я считаю, что проблема, которую выпытается решить их проблемы трекер. Там'Там идет хорошая дискуссия:https://github.com/ernie/ransack/issues/34

 Georg Ledermann23 окт. 2012 г., 16:22
Спасибо но яЯ ищу более общее решение для использования областей из Ransack. Это было возможно в Searchlogic (RIP) и в MetaSearch.

Я написал драгоценный камень под названиемсифон который помогает вам переводить параметры в области активных отношений. Комбинируя это с разграблением, можно добиться этого.

Вы можетепрочитайте полное объяснение здесь, Тем временем здесьсуть этого

Вид
= 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] имеет доброту разграбления. Теперь нам нужно найти способ распространить эти данные на объект формы. Итак, сначала позвольте 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

Ransack поддерживает это из коробки после слиянияhttps://github.com/activerecord-hackery/ransack/pull/390 , Вы должны объявить метод ransakable_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 })

Ваш ответ на вопрос