Skip to content

Instantly share code, notes, and snippets.

@nilbus
Forked from ledermann/ransack.rb
Created January 3, 2013 15:24

Revisions

  1. nilbus revised this gist Jan 3, 2013. 1 changed file with 21 additions and 13 deletions.
    34 changes: 21 additions & 13 deletions ransack.rb
    Original file line number Diff line number Diff line change
    @@ -8,39 +8,47 @@
    # end
    #
    # Ransack out of the box ignores scopes. Example:
    # Debt.ransack(:overdue => true, :amount_gteq => 10).result.to_sql
    # Debt.search(:overdue => true, :amount_gteq => 10).result.to_sql
    # => "SELECT `debts`.* FROM `debts` AND (`debts`.`amount` >= 10.0)"
    #
    # This is changed by the patch. Example:
    # Debt.ransack_with_scopes(:overdue => true).result.to_sql
    # Debt.search(:overdue => true).result.to_sql
    # => "SELECT `debts`.* FROM `debts` WHERE `debts`.`status` = 'open' AND (due_date < '2012-11-23') AND (`debts`.`amount` >= 10.0)"
    #
    # BEWARE: Every scope (and class method) of the model is available. This may be a security issue!
    #
    # Only scopes that return ActiveRecord::Relation are supported.
    # Any other scope or method that is called via Ransack will throw an exception
    # and cause a database transaction rollback.
    #
    module Ransack
    module Adapters
    module ActiveRecord
    module Base
    def ransack_with_scopes(params = {}, options = {})
    def search_with_scopes(params = {}, options = {})
    ransack_scope = self
    ransack_params = {}

    # Extract params which refer to a scope
    (params||{}).each_pair do |k,v|
    if ransack_scope.respond_to?(k)
    ransack_scope = if (v == true)
    ransack_scope.send(k)
    transaction do
    (params||{}).each_pair do |k,v|
    if ransack_scope.respond_to?(k)
    if (v == true)
    ransack_scope = ransack_scope.send(k)
    else
    ransack_scope = ransack_scope.send(k, v)
    end
    raise ArgumentError.new "#{k} is not a scope that returns an ActiveRecord::Relation" unless ransack_scope.is_a? ::ActiveRecord::Relation
    else
    ransack_scope.send(k, v)
    ransack_params.merge!(k => v)
    end
    else
    ransack_params.merge!(k => v)
    end
    end

    ransack_scope.ransack(ransack_params, options)
    ransack_scope.search_without_scopes(ransack_params, options)
    end

    alias_method_chain :search, :scopes
    end
    end
    end
    end
    end
  2. @ledermann ledermann created this gist Nov 23, 2012.
    46 changes: 46 additions & 0 deletions ransack.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,46 @@
    # Patch for ransack (https://github.com/ernie/ransack) to use scopes
    # Helps migrating from Searchlogic or MetaSearch
    # Place this file into config/initializer/ransack.rb of your Rails 3.2 project
    #
    # Usage:
    # class Debt < ActiveRecord::Base
    # scope :overdue, lambda { where(["status = 'open' AND due_date < ?", Date.today]) }
    # end
    #
    # Ransack out of the box ignores scopes. Example:
    # Debt.ransack(:overdue => true, :amount_gteq => 10).result.to_sql
    # => "SELECT `debts`.* FROM `debts` AND (`debts`.`amount` >= 10.0)"
    #
    # This is changed by the patch. Example:
    # Debt.ransack_with_scopes(:overdue => true).result.to_sql
    # => "SELECT `debts`.* FROM `debts` WHERE `debts`.`status` = 'open' AND (due_date < '2012-11-23') AND (`debts`.`amount` >= 10.0)"
    #
    # BEWARE: Every scope (and class method) of the model is available. This may be a security issue!
    #
    module Ransack
    module Adapters
    module ActiveRecord
    module Base
    def ransack_with_scopes(params = {}, options = {})
    ransack_scope = self
    ransack_params = {}

    # Extract params which refer to a scope
    (params||{}).each_pair do |k,v|
    if ransack_scope.respond_to?(k)
    ransack_scope = if (v == true)
    ransack_scope.send(k)
    else
    ransack_scope.send(k, v)
    end
    else
    ransack_params.merge!(k => v)
    end
    end

    ransack_scope.ransack(ransack_params, options)
    end
    end
    end
    end
    end