ransack_abbreviator 0.0.1
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/.gitignore +7 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +31 -0
- data/LICENSE +20 -0
- data/README.md +7 -0
- data/Rakefile +10 -0
- data/lib/ransack_abbreviator/abbreviators/decoder.rb +80 -0
- data/lib/ransack_abbreviator/abbreviators/encoder.rb +49 -0
- data/lib/ransack_abbreviator/adapters/active_record/base.rb +63 -0
- data/lib/ransack_abbreviator/adapters/active_record.rb +3 -0
- data/lib/ransack_abbreviator/configuration.rb +32 -0
- data/lib/ransack_abbreviator/constants.rb +5 -0
- data/lib/ransack_abbreviator/ransack_extensions/context.rb +34 -0
- data/lib/ransack_abbreviator/ransack_extensions/nodes/condition.rb +17 -0
- data/lib/ransack_abbreviator/ransack_extensions/nodes/grouping.rb +18 -0
- data/lib/ransack_abbreviator/ransack_extensions/search.rb +30 -0
- data/lib/ransack_abbreviator/version.rb +3 -0
- data/lib/ransack_abbreviator/view_helpers.rb +39 -0
- data/lib/ransack_abbreviator.rb +28 -0
- data/ransack_abbreviator.gemspec +27 -0
- data/spec/blueprints/articles.rb +5 -0
- data/spec/blueprints/comments.rb +5 -0
- data/spec/blueprints/notes.rb +3 -0
- data/spec/blueprints/people.rb +5 -0
- data/spec/blueprints/tags.rb +3 -0
- data/spec/ransack_abbreviator/adapters/active_record/base_spec.rb +85 -0
- data/spec/ransack_abbreviator/configuration_spec.rb +14 -0
- data/spec/ransack_abbreviator/helper_spec.rb +90 -0
- data/spec/ransack_abbreviator/search_spec.rb +379 -0
- data/spec/spec_helper.rb +47 -0
- data/spec/support/schema.rb +105 -0
- metadata +160 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
require "ostruct"
|
2
|
+
require "yaml"
|
3
|
+
require 'ransack_abbreviator/configuration'
|
4
|
+
require 'ransack_abbreviator/constants'
|
5
|
+
|
6
|
+
module RansackAbbreviator
|
7
|
+
extend Configuration
|
8
|
+
|
9
|
+
class DuplicateColumnAbbreviation < StandardError; end;
|
10
|
+
end
|
11
|
+
|
12
|
+
RansackAbbreviator.configure do |config|
|
13
|
+
parsed_config = OpenStruct.new((YAML.load_file(config.config_dir.join("ransack_abbreviator.yml")) rescue {}))
|
14
|
+
ransack_abbreviations = parsed_config.ransack_abbreviations
|
15
|
+
if !(ransack_abbreviations["columns"].values & RansackAbbreviator::Constants::RESERVED_KEYWORDS).blank? ||
|
16
|
+
!(ransack_abbreviations["associations"].values & RansackAbbreviator::Constants::RESERVED_KEYWORDS).blank?
|
17
|
+
fail "You used a reserved keyword as an abbreviation. Reserverd keywords: #{RansackAbbreviator::Constants::RESERVED_KEYWORDS.join(", ")}"
|
18
|
+
end
|
19
|
+
config.column_abbreviations = ransack_abbreviations["columns"] if ransack_abbreviations["columns"]
|
20
|
+
config.assoc_abbreviations = ransack_abbreviations["associations"] if ransack_abbreviations["associations"]
|
21
|
+
end
|
22
|
+
|
23
|
+
require "ransack_abbreviator/ransack_extensions/nodes/condition"
|
24
|
+
require "ransack_abbreviator/ransack_extensions/nodes/grouping"
|
25
|
+
require "ransack_abbreviator/ransack_extensions/context"
|
26
|
+
require "ransack_abbreviator/ransack_extensions/search"
|
27
|
+
require 'ransack_abbreviator/adapters/active_record'
|
28
|
+
require "ransack_abbreviator/view_helpers"
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "ransack_abbreviator/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "ransack_abbreviator"
|
7
|
+
s.version = RansackAbbreviator::VERSION
|
8
|
+
s.authors = ["Jamie Davidson"]
|
9
|
+
s.email = ["jhdavids8@gmail.com"]
|
10
|
+
s.homepage = "https://github.com/jhdavids8/ransack-abbreviator"
|
11
|
+
s.summary = "Avoid POSTs. Abbreviate those Ransack queries."
|
12
|
+
s.description = "Avoid POSTs. Abbreviate those Ransack queries."
|
13
|
+
|
14
|
+
s.rubyforge_project = "ransack_abbreviator"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_dependency 'ransack', '~> 0.7'
|
22
|
+
s.add_development_dependency "pry"
|
23
|
+
s.add_development_dependency 'rspec', '~> 2.8.0'
|
24
|
+
s.add_development_dependency 'machinist', '~> 1.0.6'
|
25
|
+
s.add_development_dependency 'faker', '~> 0.9.5'
|
26
|
+
s.add_development_dependency 'sqlite3', '~> 1.3.3'
|
27
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RansackAbbreviator
|
4
|
+
module Adapters
|
5
|
+
module ActiveRecord
|
6
|
+
describe Base do
|
7
|
+
subject { ::ActiveRecord::Base }
|
8
|
+
|
9
|
+
describe '#ransackable_column_abbreviations' do
|
10
|
+
subject { Person.ransackable_column_abbreviations }
|
11
|
+
|
12
|
+
it { should include 'name' => 'nm' }
|
13
|
+
it { should include 'middle_name' => 'mn' }
|
14
|
+
end
|
15
|
+
|
16
|
+
describe '#ransackable_assoc_abbreviations' do
|
17
|
+
subject { Person.ransackable_assoc_abbreviations }
|
18
|
+
|
19
|
+
it { should include 'children' => 'ch' }
|
20
|
+
it { should include 'parent' => 'pa' }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe '#ransackable_column_name_for' do
|
24
|
+
context 'when a defined abbreviation' do
|
25
|
+
it "returns the full column name" do
|
26
|
+
Person.ransackable_column_name_for("nm").should eq "name"
|
27
|
+
Person.ransackable_column_name_for("mn").should eq "middle_name"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when an undefined abbreviation' do
|
32
|
+
it "returns nil" do
|
33
|
+
Person.ransackable_column_name_for("you_fake").should be_nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe '#ransackable_column_abbr_for' do
|
39
|
+
context 'when a defined column' do
|
40
|
+
it "returns the abbreviation" do
|
41
|
+
Person.ransackable_column_abbr_for("name").should eq "nm"
|
42
|
+
Person.ransackable_column_abbr_for("middle_name").should eq "mn"
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
context 'when an undefined column' do
|
47
|
+
it "returns the passed-in column" do
|
48
|
+
Person.ransackable_column_abbr_for("you_fake").should eq "you_fake"
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe '#ransackable_assoc_name_for' do
|
54
|
+
context 'when a defined abbreviation' do
|
55
|
+
it "returns the full association name" do
|
56
|
+
Person.ransackable_assoc_name_for("ch").should eq "children"
|
57
|
+
Person.ransackable_assoc_name_for("pa").should eq "parent"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context 'when an undefined abbreviation' do
|
62
|
+
it "returns nil" do
|
63
|
+
Person.ransackable_assoc_name_for("you_fake").should be_nil
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#ransackable_assoc_abbr_for' do
|
69
|
+
context 'when a defined association' do
|
70
|
+
it "returns the abbreviation" do
|
71
|
+
Person.ransackable_assoc_abbr_for("children").should eq "ch"
|
72
|
+
Person.ransackable_assoc_abbr_for("parent").should eq "pa"
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context 'when an undefined association' do
|
77
|
+
it "returns the passed-in association" do
|
78
|
+
Person.ransackable_assoc_abbr_for("you_fake").should eq "you_fake"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module RansackAbbreviator
|
4
|
+
describe Configuration do
|
5
|
+
context "parsing a config.yml" do
|
6
|
+
it "initializes the abbreviations" do
|
7
|
+
RansackAbbreviator.column_abbreviations.should_not be_blank
|
8
|
+
RansackAbbreviator.column_abbreviations["name"].should == "nm"
|
9
|
+
RansackAbbreviator.assoc_abbreviations.should_not be_blank
|
10
|
+
RansackAbbreviator.assoc_abbreviations[:authored_article_comments].should == "a_ac"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,90 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module RansackAbbreviator
|
4
|
+
module ViewHelpers
|
5
|
+
describe "#ransack_abbreviation_for" do
|
6
|
+
context "a lookup of a defined column" do
|
7
|
+
it "returns an abbreviated column name" do
|
8
|
+
search = Ransack::Search.new(Person)
|
9
|
+
ransack_abbreviation_for(search, :name_eq).should == "nm_eq"
|
10
|
+
ransack_abbreviation_for(search, :middle_name_eq).should == "mn_eq"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
context "a lookup of an undefined column" do
|
15
|
+
it "returns the full column name" do
|
16
|
+
search = Ransack::Search.new(Person)
|
17
|
+
ransack_abbreviation_for(search, :salary_eq).should == "salary_eq"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
context "a lookup of a defined association" do
|
22
|
+
context "a lookup of a defined column" do
|
23
|
+
it "returns an abbreviated assoc & column pair" do
|
24
|
+
search = Ransack::Search.new(Article)
|
25
|
+
ransack_abbreviation_for(search, :person_name_eq).should == "pr.nm_eq"
|
26
|
+
ransack_abbreviation_for(search, :person_middle_name_eq).should == "pr.mn_eq"
|
27
|
+
search = Ransack::Search.new(Person)
|
28
|
+
ransack_abbreviation_for(search, :authored_article_comments_vote_count_lteq).should == "a_ac.vc_lteq"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "a lookup of an undefined column" do
|
33
|
+
it "returns an abbreviated table but full column" do
|
34
|
+
search = Ransack::Search.new(Article)
|
35
|
+
ransack_abbreviation_for(search, :person_salary_eq).should == "pr.salary_eq"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "a lookup of an undefined association" do
|
41
|
+
context "a lookup of a defined column" do
|
42
|
+
it "returns the full association but abbreviated column" do
|
43
|
+
search = Ransack::Search.new(Person)
|
44
|
+
ransack_abbreviation_for(search, :articles_title_cont).should == "articles.tl_cont"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context "a lookup of an undefined column" do
|
49
|
+
it "returns a full association & column pair" do
|
50
|
+
search = Ransack::Search.new(Person)
|
51
|
+
ransack_abbreviation_for(search, :articles_body_cont).should == "articles.body_cont"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context "a lookup of a multi-condition string" do
|
57
|
+
it "returns abbreviated forms for all conditions" do
|
58
|
+
search = Ransack::Search.new(Person)
|
59
|
+
ransack_abbreviation_for(search, :children_name_or_children_salary_eq).should == "ch.nm_or_ch.salary_eq"
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "a lookup of a defined polymorphic belongs_to association" do
|
64
|
+
it "returns the abbreviated name for the polymorphic association" do
|
65
|
+
search = Ransack::Search.new(Note)
|
66
|
+
ransack_abbreviation_for(search, :notable_of_Person_type_name_eq).should == "nbl_of_pr_type.nm_eq"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
context "a lookup of a nested condition" do
|
71
|
+
it "abbreviates each association and column" do
|
72
|
+
search = Ransack::Search.new(Person)
|
73
|
+
ransack_abbreviation_for(search, :articles_comments_body_cont).should == "articles_cm.body_cont"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "abbreviates nested conditions for polymorphic associations" do
|
77
|
+
search = Ransack::Search.new(Note)
|
78
|
+
ransack_abbreviation_for(search, :notable_of_Person_type_children_name_eq).should == "nbl_of_pr_type_ch.nm_eq"
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
context "a lookup of something totally random" do
|
83
|
+
it "does absolutely nothing" do
|
84
|
+
search = Ransack::Search.new(Note)
|
85
|
+
ransack_abbreviation_for(search, :i_am_garbage).should == "i_am_garbage"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
@@ -0,0 +1,379 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
module Ransack # We're testing Ransack's Search wih abbreviations
|
4
|
+
describe Search do
|
5
|
+
describe '#build' do
|
6
|
+
context "with abbreviations" do
|
7
|
+
it 'creates Conditions for top-level attributes' do
|
8
|
+
search = Search.new(Person)
|
9
|
+
search.build(ransack_abbreviation_for(search, :name_eq) => 'Ernie')
|
10
|
+
condition = search.base[:name_eq]
|
11
|
+
condition.should be_a Nodes::Condition
|
12
|
+
condition.predicate.name.should eq 'eq'
|
13
|
+
condition.attributes.first.name.should eq 'name'
|
14
|
+
condition.value.should eq 'Ernie'
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'creates Conditions for association attributes' do
|
18
|
+
search = Search.new(Person)
|
19
|
+
search.build(ransack_abbreviation_for(search, :children_name_eq) => 'Ernie')
|
20
|
+
condition = search.base[:children_name_eq]
|
21
|
+
condition.should be_a Nodes::Condition
|
22
|
+
condition.predicate.name.should eq 'eq'
|
23
|
+
condition.attributes.first.name.should eq 'children_name'
|
24
|
+
condition.value.should eq 'Ernie'
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'creates Conditions for polymorphic belongs_to association attributes' do
|
28
|
+
search = Search.new(Note)
|
29
|
+
search.build(ransack_abbreviation_for(search, :notable_of_Person_type_name_eq) => 'Ernie')
|
30
|
+
condition = search.base[:notable_of_Person_type_name_eq]
|
31
|
+
condition.should be_a Nodes::Condition
|
32
|
+
condition.predicate.name.should eq 'eq'
|
33
|
+
condition.attributes.first.name.should eq 'notable_of_Person_type_name'
|
34
|
+
condition.value.should eq 'Ernie'
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'creates Conditions for multiple polymorphic belongs_to association attributes' do
|
38
|
+
search = Search.new(Note)
|
39
|
+
search.build(ransack_abbreviation_for(search, :notable_of_Person_type_name_or_notable_of_Article_type_title_eq) => 'Ernie')
|
40
|
+
condition = search.base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
|
41
|
+
condition.should be_a Nodes::Condition
|
42
|
+
condition.predicate.name.should eq 'eq'
|
43
|
+
condition.attributes.first.name.should eq 'notable_of_Person_type_name'
|
44
|
+
condition.attributes.last.name.should eq 'notable_of_Article_type_title'
|
45
|
+
condition.value.should eq 'Ernie'
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'discards empty conditions' do
|
49
|
+
search = Search.new(Person)
|
50
|
+
search.build(ransack_abbreviation_for(search, :children_name_eq) => '')
|
51
|
+
condition = search.base[:children_name_eq]
|
52
|
+
condition.should be_nil
|
53
|
+
end
|
54
|
+
|
55
|
+
it 'accepts arrays of groupings' do
|
56
|
+
search = Search.new(Person)
|
57
|
+
search.build(
|
58
|
+
:g => [
|
59
|
+
ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'),
|
60
|
+
ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert')
|
61
|
+
]
|
62
|
+
)
|
63
|
+
ors = search.groupings
|
64
|
+
ors.should have(2).items
|
65
|
+
or1, or2 = ors
|
66
|
+
or1.should be_a Nodes::Grouping
|
67
|
+
or1.combinator.should eq 'or'
|
68
|
+
or2.should be_a Nodes::Grouping
|
69
|
+
or2.combinator.should eq 'or'
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'accepts "attributes" hashes for groupings' do
|
73
|
+
search = Search.new(Person)
|
74
|
+
search.build(
|
75
|
+
:g => {
|
76
|
+
'0' => ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'),
|
77
|
+
'1' => ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'),
|
78
|
+
}
|
79
|
+
)
|
80
|
+
ors = search.groupings
|
81
|
+
ors.should have(2).items
|
82
|
+
or1, or2 = ors
|
83
|
+
or1.should be_a Nodes::Grouping
|
84
|
+
or1.combinator.should eq 'or'
|
85
|
+
or2.should be_a Nodes::Grouping
|
86
|
+
or2.combinator.should eq 'or'
|
87
|
+
end
|
88
|
+
|
89
|
+
it 'accepts "attributes" hashes for conditions' do
|
90
|
+
search = Search.new(Person)
|
91
|
+
search.build(
|
92
|
+
:c => {
|
93
|
+
'0' => {:a => ransack_abbreviations_for(search, ['name']), :p => 'eq', :v => ['Ernie']},
|
94
|
+
'1' => {:a => ransack_abbreviations_for(search, ['children_name', 'parent_name']), :p => 'eq', :v => ['Ernie'], :m => 'or'}
|
95
|
+
}
|
96
|
+
)
|
97
|
+
conditions = search.base.conditions
|
98
|
+
conditions.should have(2).items
|
99
|
+
conditions.map {|c| c.class}.should eq [Nodes::Condition, Nodes::Condition]
|
100
|
+
end
|
101
|
+
|
102
|
+
it 'creates Conditions for custom predicates that take arrays' do
|
103
|
+
Ransack.configure do |config|
|
104
|
+
config.add_predicate 'ary_pred',
|
105
|
+
:wants_array => true
|
106
|
+
end
|
107
|
+
|
108
|
+
search = Search.new(Person)
|
109
|
+
search.build(ransack_abbreviation_for(search, :name_ary_pred) => ['Ernie', 'Bert'])
|
110
|
+
condition = search.base[:name_ary_pred]
|
111
|
+
condition.should be_a Nodes::Condition
|
112
|
+
condition.predicate.name.should eq 'ary_pred'
|
113
|
+
condition.attributes.first.name.should eq 'name'
|
114
|
+
condition.value.should eq ['Ernie', 'Bert']
|
115
|
+
end
|
116
|
+
|
117
|
+
it 'does not evaluate the query on #inspect' do
|
118
|
+
search = Search.new(Person)
|
119
|
+
search.build(ransack_abbreviation_for(search, :children_id_in) => [1, 2, 3])
|
120
|
+
search.inspect.should_not match /ActiveRecord/
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
context "without abbreviations" do
|
126
|
+
it 'creates Conditions for top-level attributes' do
|
127
|
+
search = Search.new(Person, :name_eq => 'Ernie')
|
128
|
+
condition = search.base[:name_eq]
|
129
|
+
condition.should be_a Nodes::Condition
|
130
|
+
condition.predicate.name.should eq 'eq'
|
131
|
+
condition.attributes.first.name.should eq 'name'
|
132
|
+
condition.value.should eq 'Ernie'
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'creates Conditions for association attributes' do
|
136
|
+
search = Search.new(Person, :children_name_eq => 'Ernie')
|
137
|
+
condition = search.base[:children_name_eq]
|
138
|
+
condition.should be_a Nodes::Condition
|
139
|
+
condition.predicate.name.should eq 'eq'
|
140
|
+
condition.attributes.first.name.should eq 'children_name'
|
141
|
+
condition.value.should eq 'Ernie'
|
142
|
+
end
|
143
|
+
|
144
|
+
it 'creates Conditions for polymorphic belongs_to association attributes' do
|
145
|
+
search = Search.new(Note, :notable_of_Person_type_name_eq => 'Ernie')
|
146
|
+
condition = search.base[:notable_of_Person_type_name_eq]
|
147
|
+
condition.should be_a Nodes::Condition
|
148
|
+
condition.predicate.name.should eq 'eq'
|
149
|
+
condition.attributes.first.name.should eq 'notable_of_Person_type_name'
|
150
|
+
condition.value.should eq 'Ernie'
|
151
|
+
end
|
152
|
+
|
153
|
+
it 'creates Conditions for multiple polymorphic belongs_to association attributes' do
|
154
|
+
search = Search.new(Note, :notable_of_Person_type_name_or_notable_of_Article_type_title_eq => 'Ernie')
|
155
|
+
condition = search.base[:notable_of_Person_type_name_or_notable_of_Article_type_title_eq]
|
156
|
+
condition.should be_a Nodes::Condition
|
157
|
+
condition.predicate.name.should eq 'eq'
|
158
|
+
condition.attributes.first.name.should eq 'notable_of_Person_type_name'
|
159
|
+
condition.attributes.last.name.should eq 'notable_of_Article_type_title'
|
160
|
+
condition.value.should eq 'Ernie'
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'discards empty conditions' do
|
164
|
+
search = Search.new(Person, :children_name_eq => '')
|
165
|
+
condition = search.base[:children_name_eq]
|
166
|
+
condition.should be_nil
|
167
|
+
end
|
168
|
+
|
169
|
+
it 'accepts arrays of groupings' do
|
170
|
+
search = Search.new(Person,
|
171
|
+
:g => [
|
172
|
+
{:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
|
173
|
+
{:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
|
174
|
+
]
|
175
|
+
)
|
176
|
+
ors = search.groupings
|
177
|
+
ors.should have(2).items
|
178
|
+
or1, or2 = ors
|
179
|
+
or1.should be_a Nodes::Grouping
|
180
|
+
or1.combinator.should eq 'or'
|
181
|
+
or2.should be_a Nodes::Grouping
|
182
|
+
or2.combinator.should eq 'or'
|
183
|
+
end
|
184
|
+
|
185
|
+
it 'accepts "attributes" hashes for groupings' do
|
186
|
+
search = Search.new(Person,
|
187
|
+
:g => {
|
188
|
+
'0' => {:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
|
189
|
+
'1' => {:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
|
190
|
+
}
|
191
|
+
)
|
192
|
+
ors = search.groupings
|
193
|
+
ors.should have(2).items
|
194
|
+
or1, or2 = ors
|
195
|
+
or1.should be_a Nodes::Grouping
|
196
|
+
or1.combinator.should eq 'or'
|
197
|
+
or2.should be_a Nodes::Grouping
|
198
|
+
or2.combinator.should eq 'or'
|
199
|
+
end
|
200
|
+
|
201
|
+
it 'accepts "attributes" hashes for conditions' do
|
202
|
+
search = Search.new(Person,
|
203
|
+
:c => {
|
204
|
+
'0' => {:a => ['name'], :p => 'eq', :v => ['Ernie']},
|
205
|
+
'1' => {:a => ['children_name', 'parent_name'], :p => 'eq', :v => ['Ernie'], :m => 'or'}
|
206
|
+
}
|
207
|
+
)
|
208
|
+
conditions = search.base.conditions
|
209
|
+
conditions.should have(2).items
|
210
|
+
conditions.map {|c| c.class}.should eq [Nodes::Condition, Nodes::Condition]
|
211
|
+
end
|
212
|
+
|
213
|
+
it 'creates Conditions for custom predicates that take arrays' do
|
214
|
+
Ransack.configure do |config|
|
215
|
+
config.add_predicate 'ary_pred',
|
216
|
+
:wants_array => true
|
217
|
+
end
|
218
|
+
|
219
|
+
search = Search.new(Person, :name_ary_pred => ['Ernie', 'Bert'])
|
220
|
+
condition = search.base[:name_ary_pred]
|
221
|
+
condition.should be_a Nodes::Condition
|
222
|
+
condition.predicate.name.should eq 'ary_pred'
|
223
|
+
condition.attributes.first.name.should eq 'name'
|
224
|
+
condition.value.should eq ['Ernie', 'Bert']
|
225
|
+
end
|
226
|
+
|
227
|
+
it 'does not evaluate the query on #inspect' do
|
228
|
+
search = Search.new(Person, :children_id_in => [1, 2, 3])
|
229
|
+
search.inspect.should_not match /ActiveRecord/
|
230
|
+
end
|
231
|
+
end
|
232
|
+
|
233
|
+
describe '#result' do
|
234
|
+
context "with abbreviations" do
|
235
|
+
it "evaluates a basic condition" do
|
236
|
+
search = Search.new(Person)
|
237
|
+
search.build(ransack_abbreviation_for(search, :name_eq) => 'Ernie')
|
238
|
+
search.result.should be_an ActiveRecord::Relation
|
239
|
+
where = search.result.where_values.first
|
240
|
+
where.to_sql.should match /"people"\."name" = 'Ernie'/
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'evaluates conditions contextually' do
|
244
|
+
search = Search.new(Person)
|
245
|
+
search.build(ransack_abbreviation_for(search, :children_name_eq) => 'Ernie')
|
246
|
+
search.result.should be_an ActiveRecord::Relation
|
247
|
+
where = search.result.where_values.first
|
248
|
+
where.to_sql.should match /"children_people"\."name" = 'Ernie'/
|
249
|
+
end
|
250
|
+
|
251
|
+
it 'evaluates polymorphic belongs_to association conditions contextually' do
|
252
|
+
search = Search.new(Note)
|
253
|
+
search.build(ransack_abbreviation_for(search, :notable_of_Person_type_name_eq) => 'Ernie')
|
254
|
+
search.result.should be_an ActiveRecord::Relation
|
255
|
+
where = search.result.where_values.first
|
256
|
+
where.to_sql.should match /"people"."name" = 'Ernie'/
|
257
|
+
end
|
258
|
+
|
259
|
+
it 'evaluates nested conditions' do
|
260
|
+
search = Search.new(Person)
|
261
|
+
search.build(
|
262
|
+
ransack_abbreviation_for(search, :children_name_eq) => 'Ernie',
|
263
|
+
:g => [
|
264
|
+
ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Ernie', :children_children_name_eq => 'Ernie')
|
265
|
+
]
|
266
|
+
)
|
267
|
+
search.result.should be_an ActiveRecord::Relation
|
268
|
+
where = search.result.where_values.first
|
269
|
+
where.to_sql.should match /"children_people"."name" = 'Ernie'/
|
270
|
+
where.to_sql.should match /"people"."name" = 'Ernie'/
|
271
|
+
where.to_sql.should match /"children_people_2"."name" = 'Ernie'/
|
272
|
+
end
|
273
|
+
|
274
|
+
it 'evaluates arrays of groupings' do
|
275
|
+
search = Search.new(Person)
|
276
|
+
search.build(
|
277
|
+
:g => [
|
278
|
+
ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'),
|
279
|
+
ransack_abbreviations_for(search, :m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'),
|
280
|
+
]
|
281
|
+
)
|
282
|
+
search.result.should be_an ActiveRecord::Relation
|
283
|
+
where = search.result.where_values.first
|
284
|
+
sql = where.to_sql
|
285
|
+
first, second = sql.split(/ AND /)
|
286
|
+
first.should match /"people"."name" = 'Ernie'/
|
287
|
+
first.should match /"children_people"."name" = 'Ernie'/
|
288
|
+
second.should match /"people"."name" = 'Bert'/
|
289
|
+
second.should match /"children_people"."name" = 'Bert'/
|
290
|
+
end
|
291
|
+
|
292
|
+
it 'returns distinct records when passed :distinct => true' do
|
293
|
+
search = Search.new(Person)
|
294
|
+
search.build(
|
295
|
+
:g => [ransack_abbreviations_for(search, :m => 'or', :comments_body_cont => 'e', :articles_comments_body_cont => 'e')]
|
296
|
+
)
|
297
|
+
search.result.all.should have(920).items
|
298
|
+
search.result(:distinct => true).should have(330).items
|
299
|
+
search.result.all.uniq.should eq search.result(:distinct => true).all
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
context "without abbreviations" do
|
304
|
+
it 'evaluates conditions contextually' do
|
305
|
+
search = Search.new(Person, :children_name_eq => 'Ernie')
|
306
|
+
search.result.should be_an ActiveRecord::Relation
|
307
|
+
where = search.result.where_values.first
|
308
|
+
where.to_sql.should match /"children_people"\."name" = 'Ernie'/
|
309
|
+
end
|
310
|
+
|
311
|
+
it 'evaluates compound conditions contextually' do
|
312
|
+
search = Search.new(Person, :children_name_or_name_eq => 'Ernie')
|
313
|
+
search.result.should be_an ActiveRecord::Relation
|
314
|
+
where = search.result.where_values.first
|
315
|
+
where.to_sql.should match /"children_people"\."name" = 'Ernie' OR "people"\."name" = 'Ernie'/
|
316
|
+
end
|
317
|
+
|
318
|
+
it 'evaluates polymorphic belongs_to association conditions contextually' do
|
319
|
+
search = Search.new(Note, :notable_of_Person_type_name_eq => 'Ernie')
|
320
|
+
search.result.should be_an ActiveRecord::Relation
|
321
|
+
where = search.result.where_values.first
|
322
|
+
where.to_sql.should match /"people"."name" = 'Ernie'/
|
323
|
+
end
|
324
|
+
|
325
|
+
it 'evaluates nested conditions' do
|
326
|
+
search = Search.new(Person, :children_name_eq => 'Ernie',
|
327
|
+
:g => [{
|
328
|
+
:m => 'or',
|
329
|
+
:name_eq => 'Ernie',
|
330
|
+
:children_children_name_eq => 'Ernie'
|
331
|
+
}]
|
332
|
+
)
|
333
|
+
search.result.should be_an ActiveRecord::Relation
|
334
|
+
where = search.result.where_values.first
|
335
|
+
where.to_sql.should match /"children_people"."name" = 'Ernie'/
|
336
|
+
where.to_sql.should match /"people"."name" = 'Ernie'/
|
337
|
+
where.to_sql.should match /"children_people_2"."name" = 'Ernie'/
|
338
|
+
end
|
339
|
+
|
340
|
+
it 'evaluates arrays of groupings' do
|
341
|
+
search = Search.new(Person,
|
342
|
+
:g => [
|
343
|
+
{:m => 'or', :name_eq => 'Ernie', :children_name_eq => 'Ernie'},
|
344
|
+
{:m => 'or', :name_eq => 'Bert', :children_name_eq => 'Bert'},
|
345
|
+
]
|
346
|
+
)
|
347
|
+
search.result.should be_an ActiveRecord::Relation
|
348
|
+
where = search.result.where_values.first
|
349
|
+
sql = where.to_sql
|
350
|
+
first, second = sql.split(/ AND /)
|
351
|
+
first.should match /"people"."name" = 'Ernie'/
|
352
|
+
first.should match /"children_people"."name" = 'Ernie'/
|
353
|
+
second.should match /"people"."name" = 'Bert'/
|
354
|
+
second.should match /"children_people"."name" = 'Bert'/
|
355
|
+
end
|
356
|
+
|
357
|
+
it 'returns distinct records when passed :distinct => true' do
|
358
|
+
search = Search.new(Person, :g => [{:m => 'or', :comments_body_cont => 'e', :articles_comments_body_cont => 'e'}])
|
359
|
+
search.result.all.should have(920).items
|
360
|
+
search.result(:distinct => true).should have(330).items
|
361
|
+
search.result.all.uniq.should eq search.result(:distinct => true).all
|
362
|
+
end
|
363
|
+
end
|
364
|
+
|
365
|
+
it "has the same results for a query with and without abbreviations" do
|
366
|
+
# Just some random sanity checks
|
367
|
+
search = Search.new(Person, :authored_article_comments_vote_count_lteq => 10)
|
368
|
+
abbr_search = Search.new(Person)
|
369
|
+
abbr_search.build(ransack_abbreviation_for(abbr_search, :authored_article_comments_vote_count_lteq) => 10)
|
370
|
+
search.result.where_values.first.to_sql.should eq abbr_search.result.where_values.first.to_sql
|
371
|
+
|
372
|
+
search = Search.new(Note, :notable_of_Person_type_children_name_eq => "Ernie")
|
373
|
+
abbr_search = Search.new(Note)
|
374
|
+
abbr_search.build(ransack_abbreviation_for(abbr_search, :notable_of_Person_type_children_name_eq) => "Ernie")
|
375
|
+
search.result.where_values.first.to_sql.should eq abbr_search.result.where_values.first.to_sql
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
end
|