here's bug report that reproduce the bug
begin
require 'bundler/inline'
require 'bundler'
rescue LoadError => e
STDERR.puts 'Bundler version 1.10 or later is required. Please update your Bundler'
raise e
end
gemfile(true, ui: ENV['SILENT'] ? Bundler::UI::Silent.new : Bundler::UI::Shell.new) do
source 'https://rubygems.org'
gem 'activerecord', require: false
if ENV['RANSACK_PG']
gem 'pg'
else
gem 'sqlite3', platform: :mri
gem 'activerecord-jdbcsqlite3-adapter',
git: 'https://github.com/jruby/activerecord-jdbc-adapter',
branch: 'rails-5',
platform: :jruby
end
if ENV['RANSACK_PATH']
gem 'ransack', path: ENV['RANSACK_PATH'], require: false
elsif ENV['RANSACK_VERSION']
gem 'ransack', ENV['RANSACK_VERSION'], require: false
elsif ENV['RANSACK_LATEST_GEM']
gem 'ransack', require: false
else
gem 'ransack', git: 'https://github.com/activerecord-hackery/ransack', require: false
end
end
# prepare active_record database
require 'active_record'
require 'ransack'
class NullLogger < Logger
def initialize(*_args)
end
def add(*_args, &_block)
end
end
if ENV['RANSACK_PG']
db_name = ENV['RANSACK_PG']
system("psql -c 'DROP DATABASE IF EXISTS #{db_name};'")
system("psql -c 'CREATE DATABASE #{db_name};'")
ActiveRecord::Base.establish_connection(adapter: 'postgresql', database: db_name)
else
ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
end
ActiveRecord::Base.logger = ENV['SILENT'] ? NullLogger.new : Logger.new(STDOUT)
ActiveRecord::Migration.verbose = !ENV['SILENT']
ActiveRecord::Schema.define do
# Add your schema here
create_table :reviews, force: true do |t|
t.string :content
t.integer :rank
t.boolean :is_private, default: false, null: false
end
end
# create models
class Review < ActiveRecord::Base
scope :review_private_eq, ->(flag = true) do
logger.debug { "review_private_eq called with #{flag.inspect}" }
where(is_private: flag)
end
scope :review_private_true, ->(flag = true) do
logger.debug { "review_private_true called with #{flag.inspect}" }
where(is_private: flag)
end
def self.ransackable_scopes(_auth = nil)
[:review_private_eq, :review_private_true]
end
end
# prepare tests
require 'minitest/autorun'
require 'rack/test'
# Replace this with the code necessary to make your test fail.
class BugTest < Minitest::Test
def test_ransackable_scope_eq_with_true
received_sql = ransack_sql(Review, review_private_eq: true)
expected_sql = model_sql(Review, is_private: true)
assert_equal expected_sql, received_sql
end
def test_ransackable_scope_eq_with_false
received_sql = ransack_sql(Review, review_private_eq: false)
expected_sql = model_sql(Review, is_private: false)
assert_equal expected_sql, received_sql
end
def test_ransackable_scope_eq_with_false_string
received_sql = ransack_sql(Review, review_private_eq: 'false')
expected_sql = model_sql(Review, is_private: false)
assert_equal expected_sql, received_sql
end
def test_ransackable_scope_eq_with_0_string
received_sql = ransack_sql(Review, review_private_eq: '0')
expected_sql = model_sql(Review, is_private: false)
assert_equal expected_sql, received_sql
end
def test_ransackable_scope_true_with_true
received_sql = ransack_sql(Review, review_private_true: true)
expected_sql = model_sql(Review, is_private: true)
assert_equal expected_sql, received_sql
end
def test_ransackable_scope_true_with_false
received_sql = ransack_sql(Review, review_private_true: false)
expected_sql = model_sql(Review, is_private: false)
assert_equal expected_sql, received_sql
end
def test_ransackable_scope_true_with_false_string
received_sql = ransack_sql(Review, review_private_true: 'false')
expected_sql = model_sql(Review, is_private: false)
assert_equal expected_sql, received_sql
end
def test_ransackable_scope_true_with_0_string
received_sql = ransack_sql(Review, review_private_true: '0')
expected_sql = model_sql(Review, is_private: false)
assert_equal expected_sql, received_sql
end
private
def model_sql(klass, params)
klass.where(params).to_sql
end
def ransack_sql(klass, params)
klass.ransack(params).result.to_sql
end
end
Look at the README file:
In Rails 3 and 4, if the true value is being passed via url params or some other mechanism that will convert it to a string, the true value may not be passed to the ransackable scope unless you wrap it in an array (i.e. activated: ['true']). Ransack will take care of changing 'true' into a boolean. This is currently resolved in Rails 5 :smiley:
However, perhaps you have user_id: [1] and you do not want Ransack to convert 1 into a boolean. (Values sanitized to booleans can be found in the constants.rb). To turn this off, and handle type conversions yourself, set sanitize_custom_scope_booleans to false in an initializer file like config/initializers/ransack.rb:
Ransack.configure do |c|
c.sanitize_custom_scope_booleans = false
end
@senid231 Awesome bug report! I wish all issues came with code to replicate the issue which could be added to the trunk as tests.
However, considering this is resolved in Rails 5, and there is a workaround otherwise, can we close this?
@seanfcarroll I think it can be closed now
Thanks for clarification
@luhova I have same problem with ransack to convert string to boolean, but if I disable sanitize_custom_scope_booleans , some of my search cases will die .How can I disable convert string to boolean with some scopes. Please help me.
Most helpful comment
@luhova I have same problem with ransack to convert string to boolean, but if I disable
sanitize_custom_scope_booleans, some of my search cases will die .How can I disable convert string to boolean with some scopes. Please help me.