ransack 0.5.3 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.travis.yml +7 -0
- data/Gemfile +31 -6
- data/lib/ransack/context.rb +1 -5
- data/lib/ransack/nodes/condition.rb +6 -5
- data/lib/ransack/nodes/value.rb +5 -3
- data/lib/ransack/predicate.rb +3 -2
- data/lib/ransack/version.rb +1 -1
- data/spec/ransack/adapters/active_record/base_spec.rb +32 -13
- data/spec/ransack/adapters/active_record/context_spec.rb +20 -4
- data/spec/ransack/configuration_spec.rb +20 -0
- data/spec/ransack/predicate_spec.rb +31 -1
- data/spec/ransack/search_spec.rb +11 -8
- data/spec/spec_helper.rb +13 -0
- data/spec/support/schema.rb +1 -0
- metadata +20 -17
data/.travis.yml
ADDED
data/Gemfile
CHANGED
@@ -1,14 +1,39 @@
|
|
1
1
|
source "http://rubygems.org"
|
2
2
|
gemspec
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
gem 'rake'
|
5
|
+
|
6
|
+
rails = ENV['RAILS'] || 'master'
|
7
|
+
arel = ENV['AREL'] || 'master'
|
8
|
+
|
9
|
+
arel_opts = case arel
|
10
|
+
when /\// # A path
|
11
|
+
{:path => arel}
|
12
|
+
when /^v/ # A tagged version
|
13
|
+
{:git => 'git://github.com/rails/arel.git', :tag => arel}
|
14
|
+
else
|
15
|
+
{:git => 'git://github.com/rails/arel.git', :branch => arel}
|
16
|
+
end
|
17
|
+
|
18
|
+
gem 'arel', arel_opts
|
19
|
+
|
20
|
+
case rails
|
21
|
+
when /\// # A path
|
22
|
+
gem 'activesupport', :path => "#{rails}/activesupport"
|
23
|
+
gem 'activemodel', :path => "#{rails}/activemodel"
|
24
|
+
gem 'activerecord', :path => "#{rails}/activerecord"
|
25
|
+
gem 'actionpack', :path => "#{rails}/activerecord"
|
26
|
+
when /^v/ # A tagged version
|
27
|
+
git 'git://github.com/rails/rails.git', :tag => rails do
|
28
|
+
gem 'activesupport'
|
29
|
+
gem 'activemodel'
|
30
|
+
gem 'activerecord'
|
31
|
+
gem 'actionpack'
|
32
|
+
end
|
8
33
|
else
|
9
|
-
|
10
|
-
git 'git://github.com/rails/rails.git' do
|
34
|
+
git 'git://github.com/rails/rails.git', :branch => rails do
|
11
35
|
gem 'activesupport'
|
36
|
+
gem 'activemodel'
|
12
37
|
gem 'activerecord'
|
13
38
|
gem 'actionpack'
|
14
39
|
end
|
data/lib/ransack/context.rb
CHANGED
@@ -25,10 +25,6 @@ module Ransack
|
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
def can_accept?(object)
|
29
|
-
method_defined? DISPATCH[object.class]
|
30
|
-
end
|
31
|
-
|
32
28
|
end
|
33
29
|
|
34
30
|
def initialize(object)
|
@@ -99,7 +95,7 @@ module Ransack
|
|
99
95
|
end
|
100
96
|
|
101
97
|
def unpolymorphize_association(str)
|
102
|
-
if (match = str.match(/_of_(.+?)_type$/))
|
98
|
+
if (match = str.match(/_of_(.+?)_type$/))
|
103
99
|
[match.pre_match, Kernel.const_get(match.captures.first)]
|
104
100
|
else
|
105
101
|
[str, nil]
|
@@ -16,7 +16,7 @@ module Ransack
|
|
16
16
|
:a => attributes,
|
17
17
|
:p => predicate.name,
|
18
18
|
:m => combinator,
|
19
|
-
:v => [values]
|
19
|
+
:v => %w(in not_in).include?(predicate.arel_predicate) ? Array(values) : [values]
|
20
20
|
)
|
21
21
|
# TODO: Figure out what to do with multiple types of attributes, if anything.
|
22
22
|
# Tempted to go with "garbage in, garbage out" on this one
|
@@ -41,7 +41,7 @@ module Ransack
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def valid_arity?
|
44
|
-
values.size <= 1 || predicate.
|
44
|
+
values.size <= 1 || predicate.wants_array
|
45
45
|
end
|
46
46
|
|
47
47
|
def attributes
|
@@ -113,7 +113,7 @@ module Ransack
|
|
113
113
|
end
|
114
114
|
|
115
115
|
def value
|
116
|
-
predicate.
|
116
|
+
predicate.wants_array ? values.map {|v| v.cast(default_type)} : values.first.cast(default_type)
|
117
117
|
end
|
118
118
|
|
119
119
|
def build(params)
|
@@ -180,7 +180,7 @@ module Ransack
|
|
180
180
|
end
|
181
181
|
|
182
182
|
def validated_values
|
183
|
-
values.select {|v| predicate.validator
|
183
|
+
values.select {|v| predicate.validator.call(v.value)}
|
184
184
|
end
|
185
185
|
|
186
186
|
def casted_values_for_attribute(attr)
|
@@ -188,11 +188,12 @@ module Ransack
|
|
188
188
|
end
|
189
189
|
|
190
190
|
def formatted_values_for_attribute(attr)
|
191
|
-
casted_values_for_attribute(attr).map do |val|
|
191
|
+
formatted = casted_values_for_attribute(attr).map do |val|
|
192
192
|
val = attr.ransacker.formatter.call(val) if attr.ransacker && attr.ransacker.formatter
|
193
193
|
val = predicate.format(val)
|
194
194
|
val
|
195
195
|
end
|
196
|
+
predicate.wants_array ? formatted : formatted.first
|
196
197
|
end
|
197
198
|
|
198
199
|
def default_type
|
data/lib/ransack/nodes/value.rb
CHANGED
@@ -65,10 +65,12 @@ module Ransack
|
|
65
65
|
end
|
66
66
|
|
67
67
|
def cast_to_boolean(val)
|
68
|
-
if
|
69
|
-
|
68
|
+
if Constants::TRUE_VALUES.include?(val)
|
69
|
+
true
|
70
|
+
elsif Constants::FALSE_VALUES.include?(val)
|
71
|
+
false
|
70
72
|
else
|
71
|
-
|
73
|
+
nil
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
data/lib/ransack/predicate.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Ransack
|
2
2
|
class Predicate
|
3
|
-
attr_reader :name, :arel_predicate, :type, :formatter, :validator, :compound
|
3
|
+
attr_reader :name, :arel_predicate, :type, :formatter, :validator, :compound, :wants_array
|
4
4
|
|
5
5
|
class << self
|
6
6
|
|
@@ -39,8 +39,9 @@ module Ransack
|
|
39
39
|
@arel_predicate = opts[:arel_predicate]
|
40
40
|
@type = opts[:type]
|
41
41
|
@formatter = opts[:formatter]
|
42
|
-
@validator = opts[:validator] || lambda { |v| v.
|
42
|
+
@validator = opts[:validator] || lambda { |v| v.respond_to?(:empty?) ? !v.empty? : !v.nil? }
|
43
43
|
@compound = opts[:compound]
|
44
|
+
@wants_array = @compound || ['in', 'not_in'].include?(@arel_predicate)
|
44
45
|
end
|
45
46
|
|
46
47
|
def eql?(other)
|
data/lib/ransack/version.rb
CHANGED
@@ -5,33 +5,36 @@ module Ransack
|
|
5
5
|
module ActiveRecord
|
6
6
|
describe Base do
|
7
7
|
|
8
|
-
|
9
|
-
::ActiveRecord::Base.should respond_to :ransack
|
10
|
-
end
|
8
|
+
subject { ::ActiveRecord::Base }
|
11
9
|
|
12
|
-
it
|
13
|
-
|
14
|
-
end
|
10
|
+
it { should respond_to :ransack }
|
11
|
+
it { should respond_to :search }
|
15
12
|
|
16
13
|
describe '#search' do
|
17
|
-
|
18
|
-
@s = Person.search
|
19
|
-
end
|
14
|
+
subject { Person.search }
|
20
15
|
|
21
|
-
it
|
22
|
-
|
23
|
-
|
16
|
+
it { should be_a Search }
|
17
|
+
it 'has a Relation as its object' do
|
18
|
+
subject.object.should be_an ::ActiveRecord::Relation
|
24
19
|
end
|
25
20
|
end
|
26
21
|
|
27
22
|
describe '#ransacker' do
|
23
|
+
# in schema.rb, class Person:
|
24
|
+
# ransacker :reversed_name, :formatter => proc {|v| v.reverse} do |parent|
|
25
|
+
# parent.table[:name]
|
26
|
+
# end
|
27
|
+
#
|
28
|
+
# ransacker :doubled_name do |parent|
|
29
|
+
# Arel::Nodes::InfixOperation.new('||', parent.table[:name], parent.table[:name])
|
30
|
+
# end
|
28
31
|
it 'creates ransack attributes' do
|
29
32
|
s = Person.search(:reversed_name_eq => 'htimS cirA')
|
30
33
|
s.result.should have(1).person
|
31
34
|
s.result.first.should eq Person.find_by_name('Aric Smith')
|
32
35
|
end
|
33
36
|
|
34
|
-
it '
|
37
|
+
it 'can be accessed through associations' do
|
35
38
|
s = Person.search(:children_reversed_name_eq => 'htimS cirA')
|
36
39
|
s.result.to_sql.should match /"children_people"."name" = 'Aric Smith'/
|
37
40
|
end
|
@@ -42,6 +45,22 @@ module Ransack
|
|
42
45
|
end if defined?(Arel::Nodes::InfixOperation)
|
43
46
|
end
|
44
47
|
|
48
|
+
describe '#ransackable_attributes' do
|
49
|
+
subject { Person.ransackable_attributes }
|
50
|
+
|
51
|
+
it { should include 'name' }
|
52
|
+
it { should include 'reversed_name' }
|
53
|
+
it { should include 'doubled_name' }
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#ransackable_associations' do
|
57
|
+
subject { Person.ransackable_associations }
|
58
|
+
|
59
|
+
it { should include 'parent' }
|
60
|
+
it { should include 'children' }
|
61
|
+
it { should include 'articles' }
|
62
|
+
end
|
63
|
+
|
45
64
|
end
|
46
65
|
end
|
47
66
|
end
|
@@ -4,19 +4,35 @@ module Ransack
|
|
4
4
|
module Adapters
|
5
5
|
module ActiveRecord
|
6
6
|
describe Context do
|
7
|
-
|
8
|
-
|
7
|
+
subject { Context.new(Person) }
|
8
|
+
|
9
|
+
describe '#evaluate' do
|
10
|
+
it 'evaluates search obects' do
|
11
|
+
search = Search.new(Person, :name_eq => 'Joe Blow')
|
12
|
+
result = subject.evaluate(search)
|
13
|
+
|
14
|
+
result.should be_an ::ActiveRecord::Relation
|
15
|
+
result.to_sql.should match /"name" = 'Joe Blow'/
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'SELECTs DISTINCT when :distinct => true' do
|
19
|
+
search = Search.new(Person, :name_eq => 'Joe Blow')
|
20
|
+
result = subject.evaluate(search, :distinct => true)
|
21
|
+
|
22
|
+
result.should be_an ::ActiveRecord::Relation
|
23
|
+
result.to_sql.should match /SELECT DISTINCT/
|
24
|
+
end
|
9
25
|
end
|
10
26
|
|
11
27
|
it 'contextualizes strings to attributes' do
|
12
|
-
attribute =
|
28
|
+
attribute = subject.contextualize 'children_children_parent_name'
|
13
29
|
attribute.should be_a Arel::Attributes::Attribute
|
14
30
|
attribute.name.to_s.should eq 'name'
|
15
31
|
attribute.relation.table_alias.should eq 'parents_people'
|
16
32
|
end
|
17
33
|
|
18
34
|
it 'builds new associations if not yet built' do
|
19
|
-
attribute =
|
35
|
+
attribute = subject.contextualize 'children_articles_title'
|
20
36
|
attribute.should be_a Arel::Attributes::Attribute
|
21
37
|
attribute.name.to_s.should eq 'title'
|
22
38
|
attribute.relation.name.should eq 'articles'
|
@@ -7,5 +7,25 @@ module Ransack
|
|
7
7
|
config.should eq Ransack
|
8
8
|
end
|
9
9
|
end
|
10
|
+
|
11
|
+
it 'adds predicates' do
|
12
|
+
Ransack.configure do |config|
|
13
|
+
config.add_predicate :test_predicate
|
14
|
+
end
|
15
|
+
|
16
|
+
Ransack.predicates.should have_key 'test_predicate'
|
17
|
+
Ransack.predicates.should have_key 'test_predicate_any'
|
18
|
+
Ransack.predicates.should have_key 'test_predicate_all'
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'avoids creating compound predicates if :compounds => false' do
|
22
|
+
Ransack.configure do |config|
|
23
|
+
config.add_predicate :test_predicate_without_compound, :compounds => false
|
24
|
+
end
|
25
|
+
|
26
|
+
Ransack.predicates.should have_key 'test_predicate_without_compound'
|
27
|
+
Ransack.predicates.should_not have_key 'test_predicate_without_compound_any'
|
28
|
+
Ransack.predicates.should_not have_key 'test_predicate_without_compound_all'
|
29
|
+
end
|
10
30
|
end
|
11
31
|
end
|
@@ -7,6 +7,23 @@ module Ransack
|
|
7
7
|
@s = Search.new(Person)
|
8
8
|
end
|
9
9
|
|
10
|
+
describe 'eq' do
|
11
|
+
it 'generates an equality condition for boolean true' do
|
12
|
+
@s.awesome_eq = true
|
13
|
+
@s.result.to_sql.should match /"people"."awesome" = 't'/
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'generates an equality condition for boolean false' do
|
17
|
+
@s.awesome_eq = false
|
18
|
+
@s.result.to_sql.should match /"people"."awesome" = 'f'/
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'does not generate a condition for nil' do
|
22
|
+
@s.awesome_eq = nil
|
23
|
+
@s.result.to_sql.should_not match /WHERE/
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
10
27
|
describe 'cont' do
|
11
28
|
it 'generates a LIKE query with value surrounded by %' do
|
12
29
|
@s.name_cont = 'ric'
|
@@ -21,5 +38,18 @@ module Ransack
|
|
21
38
|
end
|
22
39
|
end
|
23
40
|
|
41
|
+
describe 'null' do
|
42
|
+
it 'generates a value IS NULL query' do
|
43
|
+
@s.name_null = true
|
44
|
+
@s.result.to_sql.should match /"people"."name" IS NULL/
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe 'not_null' do
|
49
|
+
it 'generates a value IS NOT NULL query' do
|
50
|
+
@s.name_not_null = true
|
51
|
+
@s.result.to_sql.should match /"people"."name" IS NOT NULL/
|
52
|
+
end
|
53
|
+
end
|
24
54
|
end
|
25
|
-
end
|
55
|
+
end
|
data/spec/ransack/search_spec.rb
CHANGED
@@ -126,7 +126,12 @@ module Ransack
|
|
126
126
|
)
|
127
127
|
search.result.should be_an ActiveRecord::Relation
|
128
128
|
where = search.result.where_values.first
|
129
|
-
|
129
|
+
sql = where.to_sql
|
130
|
+
first, second = sql.split(/ AND /)
|
131
|
+
first.should match /"people"."name" = 'Ernie'/
|
132
|
+
first.should match /"children_people"."name" = 'Ernie'/
|
133
|
+
second.should match /"people"."name" = 'Bert'/
|
134
|
+
second.should match /"children_people"."name" = 'Bert'/
|
130
135
|
end
|
131
136
|
|
132
137
|
it 'returns distinct records when passed :distinct => true' do
|
@@ -175,13 +180,11 @@ module Ransack
|
|
175
180
|
}
|
176
181
|
}
|
177
182
|
@s.sorts.should have(2).items
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
sort2.name.should eq 'name'
|
184
|
-
sort2.dir.should eq 'asc'
|
183
|
+
@s.sorts.should be_all {|s| Nodes::Sort === s}
|
184
|
+
id_sort = @s.sorts.detect {|s| s.name == 'id'}
|
185
|
+
name_sort = @s.sorts.detect {|s| s.name == 'name'}
|
186
|
+
id_sort.dir.should eq 'desc'
|
187
|
+
name_sort.dir.should eq 'asc'
|
185
188
|
end
|
186
189
|
end
|
187
190
|
|
data/spec/spec_helper.rb
CHANGED
@@ -25,4 +25,17 @@ RSpec.configure do |config|
|
|
25
25
|
config.before(:each) { Sham.reset(:before_each) }
|
26
26
|
|
27
27
|
config.include RansackHelper
|
28
|
+
end
|
29
|
+
|
30
|
+
RSpec::Matchers.define :be_like do |expected|
|
31
|
+
match do |actual|
|
32
|
+
actual.gsub(/^\s+|\s+$/, '').gsub(/\s+/, ' ').strip ==
|
33
|
+
expected.gsub(/^\s+|\s+$/, '').gsub(/\s+/, ' ').strip
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
RSpec::Matchers.define :have_attribute_method do |expected|
|
38
|
+
match do |actual|
|
39
|
+
actual.attribute_method?(expected)
|
40
|
+
end
|
28
41
|
end
|
data/spec/support/schema.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ransack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,12 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-07-24 00:00:00.000000000 -04:00
|
13
|
+
default_executable:
|
13
14
|
dependencies:
|
14
15
|
- !ruby/object:Gem::Dependency
|
15
16
|
name: activerecord
|
16
|
-
requirement: &
|
17
|
+
requirement: &70355886036760 !ruby/object:Gem::Requirement
|
17
18
|
none: false
|
18
19
|
requirements:
|
19
20
|
- - ~>
|
@@ -21,10 +22,10 @@ dependencies:
|
|
21
22
|
version: '3.0'
|
22
23
|
type: :runtime
|
23
24
|
prerelease: false
|
24
|
-
version_requirements: *
|
25
|
+
version_requirements: *70355886036760
|
25
26
|
- !ruby/object:Gem::Dependency
|
26
27
|
name: activesupport
|
27
|
-
requirement: &
|
28
|
+
requirement: &70355886036220 !ruby/object:Gem::Requirement
|
28
29
|
none: false
|
29
30
|
requirements:
|
30
31
|
- - ~>
|
@@ -32,10 +33,10 @@ dependencies:
|
|
32
33
|
version: '3.0'
|
33
34
|
type: :runtime
|
34
35
|
prerelease: false
|
35
|
-
version_requirements: *
|
36
|
+
version_requirements: *70355886036220
|
36
37
|
- !ruby/object:Gem::Dependency
|
37
38
|
name: actionpack
|
38
|
-
requirement: &
|
39
|
+
requirement: &70355886035700 !ruby/object:Gem::Requirement
|
39
40
|
none: false
|
40
41
|
requirements:
|
41
42
|
- - ~>
|
@@ -43,10 +44,10 @@ dependencies:
|
|
43
44
|
version: '3.0'
|
44
45
|
type: :runtime
|
45
46
|
prerelease: false
|
46
|
-
version_requirements: *
|
47
|
+
version_requirements: *70355886035700
|
47
48
|
- !ruby/object:Gem::Dependency
|
48
49
|
name: rspec
|
49
|
-
requirement: &
|
50
|
+
requirement: &70355886035200 !ruby/object:Gem::Requirement
|
50
51
|
none: false
|
51
52
|
requirements:
|
52
53
|
- - ~>
|
@@ -54,10 +55,10 @@ dependencies:
|
|
54
55
|
version: 2.6.0
|
55
56
|
type: :development
|
56
57
|
prerelease: false
|
57
|
-
version_requirements: *
|
58
|
+
version_requirements: *70355886035200
|
58
59
|
- !ruby/object:Gem::Dependency
|
59
60
|
name: machinist
|
60
|
-
requirement: &
|
61
|
+
requirement: &70355886034700 !ruby/object:Gem::Requirement
|
61
62
|
none: false
|
62
63
|
requirements:
|
63
64
|
- - ~>
|
@@ -65,10 +66,10 @@ dependencies:
|
|
65
66
|
version: 1.0.6
|
66
67
|
type: :development
|
67
68
|
prerelease: false
|
68
|
-
version_requirements: *
|
69
|
+
version_requirements: *70355886034700
|
69
70
|
- !ruby/object:Gem::Dependency
|
70
71
|
name: faker
|
71
|
-
requirement: &
|
72
|
+
requirement: &70355886034140 !ruby/object:Gem::Requirement
|
72
73
|
none: false
|
73
74
|
requirements:
|
74
75
|
- - ~>
|
@@ -76,10 +77,10 @@ dependencies:
|
|
76
77
|
version: 0.9.5
|
77
78
|
type: :development
|
78
79
|
prerelease: false
|
79
|
-
version_requirements: *
|
80
|
+
version_requirements: *70355886034140
|
80
81
|
- !ruby/object:Gem::Dependency
|
81
82
|
name: sqlite3
|
82
|
-
requirement: &
|
83
|
+
requirement: &70355886033680 !ruby/object:Gem::Requirement
|
83
84
|
none: false
|
84
85
|
requirements:
|
85
86
|
- - ~>
|
@@ -87,7 +88,7 @@ dependencies:
|
|
87
88
|
version: 1.3.3
|
88
89
|
type: :development
|
89
90
|
prerelease: false
|
90
|
-
version_requirements: *
|
91
|
+
version_requirements: *70355886033680
|
91
92
|
description: Ransack is the successor to the MetaSearch gem. It improves and expands
|
92
93
|
upon MetaSearch's functionality, but does not have a 100%-compatible API.
|
93
94
|
email:
|
@@ -97,6 +98,7 @@ extensions: []
|
|
97
98
|
extra_rdoc_files: []
|
98
99
|
files:
|
99
100
|
- .gitignore
|
101
|
+
- .travis.yml
|
100
102
|
- Gemfile
|
101
103
|
- LICENSE
|
102
104
|
- README.md
|
@@ -153,6 +155,7 @@ files:
|
|
153
155
|
- spec/spec_helper.rb
|
154
156
|
- spec/support/en.yml
|
155
157
|
- spec/support/schema.rb
|
158
|
+
has_rdoc: true
|
156
159
|
homepage: http://metautonomo.us/projects/ransack
|
157
160
|
licenses: []
|
158
161
|
post_install_message:
|
@@ -173,7 +176,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
176
|
version: '0'
|
174
177
|
requirements: []
|
175
178
|
rubyforge_project: ransack
|
176
|
-
rubygems_version: 1.
|
179
|
+
rubygems_version: 1.6.2
|
177
180
|
signing_key:
|
178
181
|
specification_version: 3
|
179
182
|
summary: Object-based searching for ActiveRecord (currently).
|