aub-record_filter 0.1.1 → 0.1.2
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/VERSION.yml +1 -1
- data/lib/record_filter.rb +3 -1
- data/lib/record_filter/conjunctions.rb +19 -4
- data/lib/record_filter/dsl.rb +1 -1
- data/lib/record_filter/dsl/conjunction.rb +4 -0
- data/lib/record_filter/dsl/dsl.rb +5 -0
- data/lib/record_filter/dsl/group_by.rb +11 -0
- data/lib/record_filter/dsl/restriction.rb +2 -0
- data/lib/record_filter/group_by.rb +23 -0
- data/lib/record_filter/order.rb +4 -0
- data/lib/record_filter/query.rb +3 -1
- data/lib/record_filter/table.rb +12 -6
- data/spec/exception_spec.rb +50 -0
- data/spec/implicit_join_spec.rb +9 -9
- data/spec/limits_and_ordering_spec.rb +26 -0
- data/spec/restrictions_spec.rb +9 -0
- data/spec/test.db +0 -0
- metadata +5 -1
data/VERSION.yml
CHANGED
data/lib/record_filter.rb
CHANGED
@@ -2,9 +2,11 @@ require 'rubygems'
|
|
2
2
|
gem 'activerecord', '~> 2.2'
|
3
3
|
require 'active_record'
|
4
4
|
|
5
|
-
%w(active_record query table conjunctions restrictions filter join order dsl).each do |file|
|
5
|
+
%w(active_record query table conjunctions restrictions filter join order group_by dsl).each do |file|
|
6
6
|
require File.join(File.dirname(__FILE__), 'record_filter', file)
|
7
7
|
end
|
8
8
|
|
9
9
|
module RecordFilter
|
10
|
+
class AssociationNotFoundException < Exception; end
|
11
|
+
class ColumnNotFoundException < Exception; end
|
10
12
|
end
|
@@ -5,8 +5,8 @@ module RecordFilter
|
|
5
5
|
|
6
6
|
def self.create_from(dsl_conjunction, table)
|
7
7
|
result = case dsl_conjunction.type
|
8
|
-
when :any_of
|
9
|
-
when :all_of
|
8
|
+
when :any_of then AnyOf.new(table)
|
9
|
+
when :all_of then AllOf.new(table)
|
10
10
|
end
|
11
11
|
|
12
12
|
dsl_conjunction.steps.each do |step|
|
@@ -22,6 +22,8 @@ module RecordFilter
|
|
22
22
|
result.add_limit_and_offset(step.limit, step.offset)
|
23
23
|
when DSL::Order
|
24
24
|
result.add_order(step.column, step.direction)
|
25
|
+
when DSL::GroupBy
|
26
|
+
result.add_group_by(step.column)
|
25
27
|
end
|
26
28
|
end
|
27
29
|
result
|
@@ -35,6 +37,7 @@ module RecordFilter
|
|
35
37
|
end
|
36
38
|
|
37
39
|
def add_restriction(column_name, operator, value, options={})
|
40
|
+
check_column_exists!(column_name)
|
38
41
|
restriction_class = "RecordFilter::Restrictions::#{operator.to_s.camelize}".constantize
|
39
42
|
restriction = restriction_class.new("#{@table_name}.#{column_name}", value, options)
|
40
43
|
self << restriction
|
@@ -50,8 +53,12 @@ module RecordFilter
|
|
50
53
|
@table.join_association(association_name)
|
51
54
|
end
|
52
55
|
|
53
|
-
def add_order(
|
54
|
-
@table.order_column(
|
56
|
+
def add_order(column_name, direction)
|
57
|
+
@table.order_column(column_name, direction)
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_group_by(column_name)
|
61
|
+
@table.group_by_column(column_name)
|
55
62
|
end
|
56
63
|
|
57
64
|
def add_limit_and_offset(limit, offset)
|
@@ -79,6 +86,14 @@ module RecordFilter
|
|
79
86
|
end
|
80
87
|
end
|
81
88
|
end
|
89
|
+
|
90
|
+
protected
|
91
|
+
|
92
|
+
def check_column_exists!(column_name)
|
93
|
+
if (!@table.has_column(column_name))
|
94
|
+
raise ColumnNotFoundException.new("The column #{column_name} was not found in #{@table.table_name}.")
|
95
|
+
end
|
96
|
+
end
|
82
97
|
end
|
83
98
|
|
84
99
|
class AnyOf < Base
|
data/lib/record_filter/dsl.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
%w(conjunction conjunction_dsl dsl join limit order restriction).each { |file| require File.join(File.dirname(__FILE__), 'dsl', file) }
|
1
|
+
%w(conjunction conjunction_dsl dsl group_by join limit order restriction).each { |file| require File.join(File.dirname(__FILE__), 'dsl', file) }
|
2
2
|
|
3
3
|
module RecordFilter
|
4
4
|
module DSL
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module RecordFilter
|
2
|
+
class GroupBy
|
3
|
+
attr_reader :column, :table
|
4
|
+
|
5
|
+
def initialize(column, table)
|
6
|
+
@column, @table = column, table
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_sql
|
10
|
+
table, column = @table, @column
|
11
|
+
while column.is_a?(Hash)
|
12
|
+
table = table.join_association(column.keys[0]).right_table
|
13
|
+
column = column.values[0]
|
14
|
+
end
|
15
|
+
|
16
|
+
if (!table.has_column(column))
|
17
|
+
raise ColumnNotFoundException.new("The column #{column} was not found in #{table.table_name}.")
|
18
|
+
end
|
19
|
+
|
20
|
+
"#{table.table_name}.#{column}"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
data/lib/record_filter/order.rb
CHANGED
@@ -18,6 +18,10 @@ module RecordFilter
|
|
18
18
|
column = column.values[0]
|
19
19
|
end
|
20
20
|
|
21
|
+
if (!table.has_column(column))
|
22
|
+
raise ColumnNotFoundException.new("The column #{column} was not found in #{table.table_name}.")
|
23
|
+
end
|
24
|
+
|
21
25
|
"#{table.table_name}.#{column} #{dir}"
|
22
26
|
end
|
23
27
|
end
|
data/lib/record_filter/query.rb
CHANGED
@@ -10,8 +10,10 @@ module RecordFilter
|
|
10
10
|
params = { :conditions => @conjunction.to_conditions }
|
11
11
|
joins = @table.all_joins
|
12
12
|
params[:joins] = joins.map { |join| join.to_sql } * ' ' unless joins.empty?
|
13
|
-
orders = @table.
|
13
|
+
orders = @table.orders
|
14
14
|
params[:order] = orders.map { |order| order.to_sql } * ', ' unless orders.empty?
|
15
|
+
group_bys = @table.group_bys
|
16
|
+
params[:group] = group_bys.map { |group_by| group_by.to_sql } * ', ' unless group_bys.empty?
|
15
17
|
params[:limit] = @conjunction.limit if @conjunction.limit
|
16
18
|
params[:offset] = @conjunction.offset if @conjunction.offset
|
17
19
|
params
|
data/lib/record_filter/table.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module RecordFilter
|
2
2
|
class Table
|
3
|
-
attr_reader :table_alias
|
3
|
+
attr_reader :table_alias, :orders, :group_bys
|
4
4
|
|
5
5
|
def initialize(model_class, table_alias = nil)
|
6
6
|
@model_class = model_class
|
@@ -9,6 +9,7 @@ module RecordFilter
|
|
9
9
|
@joins_cache = {}
|
10
10
|
@joins = []
|
11
11
|
@orders = []
|
12
|
+
@group_bys = []
|
12
13
|
end
|
13
14
|
|
14
15
|
def table_name
|
@@ -19,6 +20,9 @@ module RecordFilter
|
|
19
20
|
@joins_cache[association_name] ||=
|
20
21
|
begin
|
21
22
|
association = @model_class.reflect_on_association(association_name)
|
23
|
+
if association.nil?
|
24
|
+
raise AssociationNotFoundException.new("The association #{association_name} was not found on #{@model_class.name}.")
|
25
|
+
end
|
22
26
|
case association.macro
|
23
27
|
when :belongs_to, :has_many, :has_one
|
24
28
|
simple_join(association)
|
@@ -39,11 +43,12 @@ module RecordFilter
|
|
39
43
|
@orders << Order.new(column, direction, self)
|
40
44
|
end
|
41
45
|
|
42
|
-
def
|
43
|
-
@
|
44
|
-
|
45
|
-
|
46
|
-
|
46
|
+
def group_by_column(column)
|
47
|
+
@group_bys << GroupBy.new(column, self)
|
48
|
+
end
|
49
|
+
|
50
|
+
def has_column(column_name)
|
51
|
+
@model_class.column_names.include?(column_name.to_s)
|
47
52
|
end
|
48
53
|
|
49
54
|
private
|
@@ -88,6 +93,7 @@ module RecordFilter
|
|
88
93
|
@joins_cache = {}
|
89
94
|
@joins = []
|
90
95
|
@orders = []
|
96
|
+
@group_bys = []
|
91
97
|
end
|
92
98
|
end
|
93
99
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe 'raising exceptions' do
|
4
|
+
|
5
|
+
describe 'on missing associations' do
|
6
|
+
it 'should get AssociationNotFoundException' do
|
7
|
+
lambda {
|
8
|
+
Post.filter do
|
9
|
+
having(:something_that_does_not_exist) do
|
10
|
+
with(:something_bad)
|
11
|
+
end
|
12
|
+
end.inspect
|
13
|
+
}.should raise_error(RecordFilter::AssociationNotFoundException)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe 'on missing columns' do
|
18
|
+
it 'should get ColumnNotFoundException for with' do
|
19
|
+
lambda {
|
20
|
+
Post.filter do
|
21
|
+
with(:this_is_not_there, 2)
|
22
|
+
end.inspect
|
23
|
+
}.should raise_error(RecordFilter::ColumnNotFoundException)
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'should get ColumnNotFoundException for without' do
|
27
|
+
lambda {
|
28
|
+
Post.filter do
|
29
|
+
without(:this_is_not_there, 2)
|
30
|
+
end.inspect
|
31
|
+
}.should raise_error(RecordFilter::ColumnNotFoundException)
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'should get ColumnNotFoundException for order' do
|
35
|
+
lambda {
|
36
|
+
Post.filter do
|
37
|
+
order(:this_is_not_there, :asc)
|
38
|
+
end.inspect
|
39
|
+
}.should raise_error(RecordFilter::ColumnNotFoundException)
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should get AssociationNotFoundException for orders on bad associations' do
|
43
|
+
lambda {
|
44
|
+
Post.filter do
|
45
|
+
order({ :this_is_not_there => :eh }, :asc)
|
46
|
+
end.inspect
|
47
|
+
}.should raise_error(RecordFilter::AssociationNotFoundException)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
data/spec/implicit_join_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe 'implicit joins' do
|
|
9
9
|
describe 'with single condition inline' do
|
10
10
|
before do
|
11
11
|
Post.filter do
|
12
|
-
having(:blog).with :
|
12
|
+
having(:blog).with :name, 'Test Name'
|
13
13
|
end.inspect
|
14
14
|
end
|
15
15
|
|
@@ -18,7 +18,7 @@ describe 'implicit joins' do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it 'should query against condition on join table' do
|
21
|
-
Post.last_find[:conditions].should == ['posts__blog.
|
21
|
+
Post.last_find[:conditions].should == ['posts__blog.name = ?', 'Test Name']
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -28,14 +28,14 @@ describe 'implicit joins' do
|
|
28
28
|
end
|
29
29
|
|
30
30
|
it 'should query against conditions on join table' do
|
31
|
-
Post.last_find[:conditions].should == [%q((posts__blog.
|
31
|
+
Post.last_find[:conditions].should == [%q((posts__blog.name = ?) AND (posts__blog.published = ?)), 'Test Name', true]
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
describe 'with multiple conditions on single join inline' do
|
36
36
|
before do
|
37
37
|
Post.filter do
|
38
|
-
having(:blog).with :
|
38
|
+
having(:blog).with :name, 'Test Name'
|
39
39
|
having(:blog).with :published, true
|
40
40
|
end.inspect
|
41
41
|
end
|
@@ -47,7 +47,7 @@ describe 'implicit joins' do
|
|
47
47
|
before do
|
48
48
|
Post.filter do
|
49
49
|
having :blog do
|
50
|
-
with :
|
50
|
+
with :name, 'Test Name'
|
51
51
|
with :published, true
|
52
52
|
end
|
53
53
|
end.inspect
|
@@ -154,13 +154,13 @@ describe 'implicit joins' do
|
|
154
154
|
describe 'with nil conditions' do
|
155
155
|
before do
|
156
156
|
Comment.filter do
|
157
|
-
with :
|
157
|
+
with :contents, nil
|
158
158
|
with :offensive, true
|
159
159
|
end.inspect
|
160
160
|
end
|
161
161
|
|
162
162
|
it 'should create the correct IS NULL condition' do
|
163
|
-
Comment.last_find[:conditions].should == [%q(("comments".
|
163
|
+
Comment.last_find[:conditions].should == [%q(("comments".contents IS NULL) AND ("comments".offensive = ?)), true]
|
164
164
|
end
|
165
165
|
end
|
166
166
|
|
@@ -179,13 +179,13 @@ describe 'implicit joins' do
|
|
179
179
|
describe 'with negated nil conditions' do
|
180
180
|
before do
|
181
181
|
Comment.filter do
|
182
|
-
without :
|
182
|
+
without :contents, nil
|
183
183
|
with :offensive, true
|
184
184
|
end.inspect
|
185
185
|
end
|
186
186
|
|
187
187
|
it 'should create the correct IS NOT NULL condition' do
|
188
|
-
Comment.last_find[:conditions].should == [%q(("comments".
|
188
|
+
Comment.last_find[:conditions].should == [%q(("comments".contents IS NOT NULL) AND ("comments".offensive = ?)), true]
|
189
189
|
end
|
190
190
|
end
|
191
191
|
end
|
@@ -161,4 +161,30 @@ describe 'filter qualifiers' do
|
|
161
161
|
end
|
162
162
|
end
|
163
163
|
end
|
164
|
+
|
165
|
+
describe 'group_by' do
|
166
|
+
it 'should add the group for a simple column' do
|
167
|
+
Post.filter do
|
168
|
+
group_by(:created_at)
|
169
|
+
end.inspect
|
170
|
+
Post.last_find[:group].should == %q("posts".created_at)
|
171
|
+
end
|
172
|
+
|
173
|
+
it 'should add the group for multiple column' do
|
174
|
+
Post.filter do
|
175
|
+
group_by(:created_at)
|
176
|
+
group_by(:published)
|
177
|
+
end.inspect
|
178
|
+
Post.last_find[:group].should == %q("posts".created_at, "posts".published)
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'should add the group for joined columns' do
|
182
|
+
Post.filter do
|
183
|
+
having(:photo)
|
184
|
+
group_by(:created_at)
|
185
|
+
group_by(:photo => :format)
|
186
|
+
end.inspect
|
187
|
+
Post.last_find[:group].should == %q("posts".created_at, "photos".format)
|
188
|
+
end
|
189
|
+
end
|
164
190
|
end
|
data/spec/restrictions_spec.rb
CHANGED
@@ -75,4 +75,13 @@ describe 'RecordFilter restrictions' do
|
|
75
75
|
Post.last_find.should == { :conditions => [%q{(("posts".blog_id = ?) AND ("posts".permalink = ?)) OR ("posts".permalink = ?)},
|
76
76
|
1, 'my-post', 'another-post'] }
|
77
77
|
end
|
78
|
+
|
79
|
+
it 'should filter for nil' do
|
80
|
+
[:is_null, :null, :nil].each do |method|
|
81
|
+
Post.filter do
|
82
|
+
with(:permalink).send(method)
|
83
|
+
end.inspect
|
84
|
+
Post.last_find.should == { :conditions => [%q("posts".permalink IS NULL)] }
|
85
|
+
end
|
86
|
+
end
|
78
87
|
end
|
data/spec/test.db
CHANGED
Binary file
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: aub-record_filter
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mat Brown
|
@@ -32,17 +32,20 @@ files:
|
|
32
32
|
- lib/record_filter/dsl/conjunction.rb
|
33
33
|
- lib/record_filter/dsl/conjunction_dsl.rb
|
34
34
|
- lib/record_filter/dsl/dsl.rb
|
35
|
+
- lib/record_filter/dsl/group_by.rb
|
35
36
|
- lib/record_filter/dsl/join.rb
|
36
37
|
- lib/record_filter/dsl/limit.rb
|
37
38
|
- lib/record_filter/dsl/order.rb
|
38
39
|
- lib/record_filter/dsl/restriction.rb
|
39
40
|
- lib/record_filter/filter.rb
|
41
|
+
- lib/record_filter/group_by.rb
|
40
42
|
- lib/record_filter/join.rb
|
41
43
|
- lib/record_filter/join_table.rb
|
42
44
|
- lib/record_filter/order.rb
|
43
45
|
- lib/record_filter/query.rb
|
44
46
|
- lib/record_filter/restrictions.rb
|
45
47
|
- lib/record_filter/table.rb
|
48
|
+
- spec/exception_spec.rb
|
46
49
|
- spec/implicit_join_spec.rb
|
47
50
|
- spec/limits_and_ordering_spec.rb
|
48
51
|
- spec/models/blog.rb
|
@@ -81,6 +84,7 @@ signing_key:
|
|
81
84
|
specification_version: 3
|
82
85
|
summary: Pure-ruby criteria API for building complex queries in ActiveRecord
|
83
86
|
test_files:
|
87
|
+
- spec/exception_spec.rb
|
84
88
|
- spec/implicit_join_spec.rb
|
85
89
|
- spec/limits_and_ordering_spec.rb
|
86
90
|
- spec/models/blog.rb
|