Relata 0.0.2 → 0.0.3
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/Rakefile +1 -1
- data/init.rb +1 -1
- data/lib/relata.rb +3 -0
- data/lib/relata/dsl.rb +42 -0
- data/lib/relata/dsl/conditions.rb +65 -0
- data/lib/{filtered_relation → relata}/dsl/constraints.rb +20 -7
- data/lib/relata/dsl/custom_relation.rb +44 -0
- data/lib/relata/dsl/field_search.rb +111 -0
- data/lib/relata/dsl/missed_builder.rb +28 -0
- data/lib/relata/dsl/querys/belongs.rb +8 -0
- data/lib/{filtered_relation → relata}/dsl/querys/fields.rb +9 -4
- data/lib/{filtered_relation → relata}/dsl/querys/multiple.rb +0 -0
- data/lib/{filtered_relation → relata}/dsl/querys/simple.rb +0 -0
- data/lib/{filtered_relation → relata}/filter.rb +20 -0
- data/lib/{filtered_relation → relata}/related_query_methods.rb +0 -0
- data/test.sqlite3 +0 -0
- data/test/dsl_test.rb +96 -39
- data/test/filtered_relation_test.rb +40 -40
- data/test/relation_dsl_test.rb +57 -0
- data/test/schema.rb +14 -0
- metadata +17 -12
- data/lib/filtered_relation.rb +0 -3
- data/lib/filtered_relation/dsl.rb +0 -109
- data/lib/filtered_relation/dsl/conditions.rb +0 -36
data/Rakefile
CHANGED
@@ -27,7 +27,7 @@ PKG_FILES = FileList[ '[a-zA-Z]*', 'generators/**/*', 'lib/**/*', 'rails/**/*',
|
|
27
27
|
|
28
28
|
spec = Gem::Specification.new do |s|
|
29
29
|
s.name = "Relata"
|
30
|
-
s.version = "0.0.
|
30
|
+
s.version = "0.0.3"
|
31
31
|
s.author = "Anderson Leite, Guilherme Silveira"
|
32
32
|
s.email = "anderson.leite@caelum.com.br"
|
33
33
|
s.homepage = "http://github.com/caelum/relata"
|
data/init.rb
CHANGED
data/lib/relata.rb
ADDED
data/lib/relata/dsl.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
# in case you did not require the entire relata plugin
|
2
|
+
module Relata
|
3
|
+
module Dsl
|
4
|
+
end
|
5
|
+
end
|
6
|
+
|
7
|
+
require 'relata/dsl/conditions'
|
8
|
+
require 'relata/dsl/constraints'
|
9
|
+
require 'relata/dsl/custom_relation'
|
10
|
+
require 'relata/dsl/field_search'
|
11
|
+
require 'relata/dsl/missed_builder'
|
12
|
+
require 'relata/dsl/querys/multiple'
|
13
|
+
require 'relata/dsl/querys/simple'
|
14
|
+
require 'relata/dsl/querys/fields'
|
15
|
+
require 'relata/dsl/querys/belongs'
|
16
|
+
|
17
|
+
module Relata::Dsl::Relation
|
18
|
+
|
19
|
+
# extended where clause that allows symbol and custom dsl lookup
|
20
|
+
#
|
21
|
+
# examples:
|
22
|
+
# where(:body).like?("%guilherme%")
|
23
|
+
# where { body.like?("%guilherme%")
|
24
|
+
#
|
25
|
+
# While the last will delegate to the MissedBuilder component
|
26
|
+
# the symbol based query will delegate query builder to CustomRelation.
|
27
|
+
def where(*args, &block)
|
28
|
+
if args.size==0 && block
|
29
|
+
Relata::Dsl::MissedBuilder.new(self).instance_eval(&block)
|
30
|
+
elsif args.size==1 && args[0].is_a?(Symbol)
|
31
|
+
relation = scoped
|
32
|
+
relation.extend Relata::Dsl::CustomRelation
|
33
|
+
relation.using(self, args[0])
|
34
|
+
else
|
35
|
+
super(*args, &block)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
class ActiveRecord::Relation
|
41
|
+
include Relata::Dsl::Relation
|
42
|
+
end
|
@@ -0,0 +1,65 @@
|
|
1
|
+
# = Conditions
|
2
|
+
# A custom set of conditions that can be applied
|
3
|
+
# to a query
|
4
|
+
module Relata::Dsl::Conditions
|
5
|
+
|
6
|
+
# Return all objects whith exactly X associated objects
|
7
|
+
# Post.where(:comments).count.eq(2)
|
8
|
+
def eq(value)
|
9
|
+
add_filter("= #{value}")
|
10
|
+
end
|
11
|
+
|
12
|
+
# Return all objects whith more or exactly X associated objects
|
13
|
+
# Post.where(:comments).count.ge(2)
|
14
|
+
def ge(value)
|
15
|
+
add_filter(">= #{value}")
|
16
|
+
end
|
17
|
+
|
18
|
+
# Return all objects whith more or exactly X associated objects
|
19
|
+
# Post.where(:comments).count.greater_or_equals(2)
|
20
|
+
def greater_or_equals(value)
|
21
|
+
ge(value)
|
22
|
+
end
|
23
|
+
|
24
|
+
# Return all objects whith more than X associated objects
|
25
|
+
# Post.where(:comments).count.gt(2)
|
26
|
+
def gt(value)
|
27
|
+
add_filter("> #{value}")
|
28
|
+
end
|
29
|
+
|
30
|
+
# Return all objects whith more than X associated objects
|
31
|
+
# Alias for "gt"
|
32
|
+
# Post.where(:comments).count.greater_than(2)
|
33
|
+
def greater_than(value)
|
34
|
+
gt(value)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Return all objects whith less or equals X associated objects
|
38
|
+
# Post.where(:comments).count.le(2)
|
39
|
+
def le(value)
|
40
|
+
add_filter("<= #{value}")
|
41
|
+
end
|
42
|
+
|
43
|
+
# Return all objects whith less than X associated objects
|
44
|
+
# Post.where(:comments).count.lt(2)
|
45
|
+
def lt(value)
|
46
|
+
add_filter("< #{value}")
|
47
|
+
end
|
48
|
+
|
49
|
+
# Return all objects whith less than X associated object
|
50
|
+
# Alias for "lt"
|
51
|
+
# Post.where(:comments).count.lesser_than(2)
|
52
|
+
def lesser_than(value)
|
53
|
+
lt value
|
54
|
+
end
|
55
|
+
|
56
|
+
# Whether this relation has at least one element.
|
57
|
+
# Post.where(:comments).exists?
|
58
|
+
def exists?
|
59
|
+
if @relation_search.nil?
|
60
|
+
count.exists?
|
61
|
+
else
|
62
|
+
add_filter("> 0")
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
@@ -1,16 +1,15 @@
|
|
1
|
-
|
1
|
+
# = Constraints
|
2
|
+
# A custom set of constraints that can be applied
|
3
|
+
# to a query
|
4
|
+
module Relata::Dsl::Constraints
|
2
5
|
|
6
|
+
# Return all objects which fields by size
|
7
|
+
# Post.where { body.length < 22 }
|
3
8
|
def length
|
4
9
|
@relation_search = LengthManager
|
5
10
|
self
|
6
11
|
end
|
7
12
|
|
8
|
-
class LengthManager
|
9
|
-
def self.condition(field, *args)
|
10
|
-
"len(field)"
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|
14
13
|
def count
|
15
14
|
@select_fields << "COUNT(#{@current_field}.id) AS count"
|
16
15
|
@groups << "#{table_name}.id"
|
@@ -18,9 +17,17 @@ module Constraints
|
|
18
17
|
self
|
19
18
|
end
|
20
19
|
|
20
|
+
# Return all objects which match with parameter
|
21
|
+
# Post.where(:body).like?("%caelum%")
|
21
22
|
def like?(value)
|
22
23
|
query.where("#{@current_field} like ?", [value])
|
23
24
|
end
|
25
|
+
|
26
|
+
# Return all objects whith nil value fields
|
27
|
+
# Post.where(:body).is_null
|
28
|
+
def is_null
|
29
|
+
query.where("#{@current_field} is NULL")
|
30
|
+
end
|
24
31
|
|
25
32
|
# def between(first, second)
|
26
33
|
# @relation_search = SimpleRangeCondition
|
@@ -29,6 +36,12 @@ module Constraints
|
|
29
36
|
# # add_filter("> #{first}").add_filter("< #{second}")
|
30
37
|
# end
|
31
38
|
|
39
|
+
class LengthManager
|
40
|
+
def self.condition(field, *args)
|
41
|
+
"len(field)"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
32
45
|
class SimpleCondition
|
33
46
|
def self.condition(field, *args)
|
34
47
|
"#{field}"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# defines helper methods to deal with custom relation
|
2
|
+
module Relata::Dsl::CustomRelation
|
3
|
+
include Relata::Dsl::Conditions
|
4
|
+
include Relata::Dsl::Constraints
|
5
|
+
|
6
|
+
def using(record, field)
|
7
|
+
@record = record
|
8
|
+
@current_field = field
|
9
|
+
@start_field = field
|
10
|
+
@select_fields = ["#{table_name}.*"]
|
11
|
+
@groups = []
|
12
|
+
|
13
|
+
if relates_to_many?
|
14
|
+
self.extend MultipleQuery
|
15
|
+
self.extend ModelFields
|
16
|
+
elsif relates_belongs_to?
|
17
|
+
self.extend BelongsToQuery
|
18
|
+
self.extend ModelFields
|
19
|
+
else
|
20
|
+
self.extend SimpleQuery
|
21
|
+
end
|
22
|
+
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
def relates_to_many?
|
27
|
+
@record.reflect_on_all_associations.each do |r|
|
28
|
+
if r.name.to_sym.eql? @current_field.to_sym
|
29
|
+
return true if r.macro.to_s.eql? "has_many"
|
30
|
+
end
|
31
|
+
end
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
def relates_belongs_to?
|
36
|
+
@record.reflect_on_all_associations.each do |r|
|
37
|
+
if r.name.to_sym.eql? @current_field.to_sym
|
38
|
+
return true if r.macro.to_s.eql? "belongs_to"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
false
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# = Field Search
|
2
|
+
# a relation search in a specific field
|
3
|
+
class Relata::Dsl::FieldSearch
|
4
|
+
|
5
|
+
def initialize(rel, field)
|
6
|
+
@rel = rel
|
7
|
+
@field = field
|
8
|
+
end
|
9
|
+
|
10
|
+
# Exactly number of relation or field value
|
11
|
+
# Post.where { body == "CaelumObjects training and inovation" }
|
12
|
+
# Post.where { comments == 2 }
|
13
|
+
def ==(value)
|
14
|
+
@rel.where("#{@field} == ?", value)
|
15
|
+
end
|
16
|
+
|
17
|
+
# All records with different field value
|
18
|
+
# Post.where { comments == 2 }
|
19
|
+
def !=(value)
|
20
|
+
@rel.where("#{@field} <> ?", value)
|
21
|
+
end
|
22
|
+
|
23
|
+
# All records with higher or equal number of relations
|
24
|
+
# Post.where { comments >= 2 }
|
25
|
+
def >=(value)
|
26
|
+
@rel.where("#{@field} >= ?", value)
|
27
|
+
end
|
28
|
+
|
29
|
+
# All records with less or equal number of relations
|
30
|
+
# Post.where { comments <= 2 }
|
31
|
+
def <=(value)
|
32
|
+
@rel.where("#{@field} <= ?", value)
|
33
|
+
end
|
34
|
+
|
35
|
+
# All records with higher number of relations
|
36
|
+
# Post.where { comments > 2 }
|
37
|
+
def >(value)
|
38
|
+
@rel.where("#{@field} > ?", value)
|
39
|
+
end
|
40
|
+
|
41
|
+
# All records with lesser number of relations
|
42
|
+
# Post.where { comments < 2 }
|
43
|
+
def <(value)
|
44
|
+
@rel.where("#{@field} < ?", value)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Find records by field value
|
48
|
+
# Post.where(:body).like?("%caelum%")
|
49
|
+
def like?(value)
|
50
|
+
@rel.where(@field).like?(value)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Find record with date between
|
54
|
+
# Post.where { published_at.between(2.years.ago, 6.months.ago) }
|
55
|
+
def between(first, second)
|
56
|
+
@rel.where("#{@field} > ? and #{@field} < ?", first, second)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Find records by size
|
60
|
+
# Post.where { body.length < 22 }
|
61
|
+
def length
|
62
|
+
@field = "length(#{@field})"
|
63
|
+
self
|
64
|
+
end
|
65
|
+
|
66
|
+
# Your custom relation
|
67
|
+
# Post.where { body "like ?", "%lum%" }
|
68
|
+
def custom(*args)
|
69
|
+
comparison = args.shift
|
70
|
+
@rel.where("#{@field} #{comparison}", args)
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
class Relata::Dsl::FieldSearchMany
|
76
|
+
|
77
|
+
def initialize(rel, field)
|
78
|
+
@rel = rel
|
79
|
+
@field = field
|
80
|
+
end
|
81
|
+
|
82
|
+
def ==(value)
|
83
|
+
@rel.where(@field).count.eq(value)
|
84
|
+
end
|
85
|
+
|
86
|
+
def >=(value)
|
87
|
+
@rel.where(@field).count.ge(value)
|
88
|
+
end
|
89
|
+
|
90
|
+
def <=(value)
|
91
|
+
@rel.where(@field).count.le(value)
|
92
|
+
end
|
93
|
+
|
94
|
+
def >(value)
|
95
|
+
@rel.where(@field).count.gt(value)
|
96
|
+
end
|
97
|
+
|
98
|
+
def <(value)
|
99
|
+
@rel.where(@field).count.lt(value)
|
100
|
+
end
|
101
|
+
|
102
|
+
def exists?
|
103
|
+
@rel.where(@field).exists?
|
104
|
+
end
|
105
|
+
|
106
|
+
def custom(*args)
|
107
|
+
comparison = args.shift
|
108
|
+
@rel.where("#{@field} #{comparison}", args)
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# a builder ready to collect which field you want to search
|
2
|
+
class Relata::Dsl::MissedBuilder
|
3
|
+
|
4
|
+
def initialize(rel)
|
5
|
+
@rel = rel
|
6
|
+
end
|
7
|
+
|
8
|
+
def method_missing(field, *args)
|
9
|
+
relation = @rel.scoped
|
10
|
+
relation.extend Relata::Dsl::CustomRelation
|
11
|
+
relation.using(@rel, field)
|
12
|
+
|
13
|
+
if relation.relates_to_many?
|
14
|
+
type = Relata::Dsl::FieldSearchMany
|
15
|
+
else
|
16
|
+
type = Relata::Dsl::FieldSearch
|
17
|
+
end
|
18
|
+
|
19
|
+
instance = type.new(relation, field)
|
20
|
+
|
21
|
+
if args.size != 0
|
22
|
+
instance = instance.custom(*args)
|
23
|
+
end
|
24
|
+
|
25
|
+
instance
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
module BelongsToQuery
|
2
|
+
def query
|
3
|
+
preload(@start_field).select(@select_fields.join ',').from("#{table_name}, #{@start_field.to_s.pluralize}").where("#{table_name}.#{@start_field}_id = #{@start_field.to_s.pluralize}.id")
|
4
|
+
end
|
5
|
+
def add_filter expectation
|
6
|
+
query.group(@groups.first).having("#{@relation_search} #{expectation}")
|
7
|
+
end
|
8
|
+
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
module ModelFields
|
2
2
|
|
3
3
|
def self.extended(base)
|
4
|
-
|
4
|
+
@fields = []
|
5
5
|
base.reflect_on_all_associations.each do |r|
|
6
|
-
|
7
|
-
c.name if [:string, :text].include? c.type
|
6
|
+
r.klass.columns.each do |c|
|
7
|
+
@fields << c.name if [:string, :text].include? c.type
|
8
8
|
end
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
@fields.each do |field|
|
12
12
|
include_method field if field != nil
|
13
13
|
end
|
@@ -17,6 +17,11 @@ module ModelFields
|
|
17
17
|
private
|
18
18
|
def self.include_method(field)
|
19
19
|
define_method field do
|
20
|
+
|
21
|
+
@record.reflect_on_all_associations.each do |r|
|
22
|
+
@current_field = @current_field.to_s.pluralize if r.macro.to_s.eql? "belongs_to"
|
23
|
+
end
|
24
|
+
|
20
25
|
@current_field = "#{@current_field}.#{field}"
|
21
26
|
self
|
22
27
|
end
|
File without changes
|
File without changes
|
@@ -1,6 +1,26 @@
|
|
1
1
|
require 'filtered_relation/related_query_methods'
|
2
2
|
ActiveRecord::Base.send :include, RelatedQueryMethods
|
3
3
|
|
4
|
+
|
5
|
+
# = Filtered Relation
|
6
|
+
# Create dynamic filters with just onde method.
|
7
|
+
|
8
|
+
# <% form_tag :action => 'filter' do %>
|
9
|
+
# Title: <%= text_field_tag 'post[title]' %><br />
|
10
|
+
# Only with Comments?
|
11
|
+
# <%= select("post", "comments", options_for_select({ "false" => "", "true" => "true" })) %> %>
|
12
|
+
#
|
13
|
+
# def filter
|
14
|
+
# @posts = Post.filtered_relation(params[:post]).all
|
15
|
+
# end
|
16
|
+
|
17
|
+
# Create more advanced relations with DSL.
|
18
|
+
|
19
|
+
# posts = Post.filtered_relation(:comments => true).where(:user_id => 4).limit(3).order("id ASC")
|
20
|
+
|
21
|
+
# posts.each do |post|
|
22
|
+
# # records
|
23
|
+
# end
|
4
24
|
module FilteredRelation
|
5
25
|
|
6
26
|
class ::ActiveRecord::Base
|
File without changes
|
data/test.sqlite3
CHANGED
Binary file
|
data/test/dsl_test.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__)) + "/test_helper"
|
2
2
|
require 'schema'
|
3
|
-
require '
|
3
|
+
require 'relata/dsl'
|
4
4
|
|
5
5
|
class DSLTest < ActiveSupport::TestCase
|
6
6
|
|
@@ -14,17 +14,17 @@ class DSLTest < ActiveSupport::TestCase
|
|
14
14
|
posts = Post.where(:body).like?("%caelum%").all
|
15
15
|
assert_equal @caelum, posts[0]
|
16
16
|
assert_equal 1, posts.size
|
17
|
-
|
17
|
+
|
18
18
|
posts = Post.where { body.like? "%caelum%" }
|
19
19
|
assert_equal @caelum, posts[0]
|
20
20
|
assert_equal 1, posts.size
|
21
21
|
end
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
23
|
+
test "given an attribute and constraint expectation, gives the results" do
|
24
|
+
posts = Post.where { body.length < 22 }
|
25
|
+
assert_equal @guilherme, posts[0]
|
26
|
+
assert_equal 1, posts.size
|
27
|
+
end
|
28
28
|
|
29
29
|
test "exists posts with comments" do
|
30
30
|
@caelum.update_attributes(:comments => [Comment.create])
|
@@ -38,7 +38,7 @@ class DSLTest < ActiveSupport::TestCase
|
|
38
38
|
posts = Post.where(:comments).exists?
|
39
39
|
assert_equal @caelum, posts[0]
|
40
40
|
assert_equal 1, posts.size
|
41
|
-
|
41
|
+
|
42
42
|
posts = Post.where { comments.exists? }
|
43
43
|
assert_equal @caelum, posts[0]
|
44
44
|
assert_equal 1, posts.size
|
@@ -61,64 +61,121 @@ class DSLTest < ActiveSupport::TestCase
|
|
61
61
|
test "exists posts with more than or equals 2 comments" do
|
62
62
|
@caelum.update_attributes(:comments => [Comment.create, Comment.create])
|
63
63
|
@guilherme.update_attributes(:comments => [Comment.create, Comment.create, Comment.create])
|
64
|
-
|
65
|
-
posts = Post.where(:comments).count.ge(2)
|
64
|
+
|
65
|
+
posts = Post.where(:comments).count.ge(2).all
|
66
|
+
assert_equal 2, posts.size
|
66
67
|
assert_equal @caelum, posts[0]
|
67
68
|
assert_equal @guilherme, posts[1]
|
68
|
-
assert_equal 2, posts.size
|
69
69
|
end
|
70
70
|
|
71
|
-
test "
|
72
|
-
|
73
|
-
@
|
74
|
-
|
75
|
-
posts = Post.where(:comments).
|
76
|
-
assert_equal @caelum, posts
|
77
|
-
assert_equal 1, posts.size
|
78
|
-
|
71
|
+
test "dsl query supports first" do
|
72
|
+
@caelum.update_attributes(:comments => [Comment.create, Comment.create])
|
73
|
+
@guilherme.update_attributes(:comments => [Comment.create, Comment.create, Comment.create])
|
74
|
+
|
75
|
+
posts = Post.where(:comments).count.ge(2).first
|
76
|
+
assert_equal @caelum, posts
|
79
77
|
end
|
80
|
-
|
78
|
+
|
81
79
|
test "exists posts using strict extended methods" do
|
82
80
|
@caelum.update_attributes(:comments => [Comment.create, Comment.create])
|
83
81
|
@guilherme.update_attributes(:comments => [Comment.create, Comment.create, Comment.create])
|
84
82
|
posts = Post.where { comments >= 2 }
|
85
83
|
assert_equal @caelum, posts[0]
|
84
|
+
assert_equal 2, posts.size
|
86
85
|
assert_equal @guilherme, posts[1]
|
86
|
+
end
|
87
|
+
|
88
|
+
test "strict block supports first" do
|
89
|
+
@caelum.update_attributes(:comments => [Comment.create, Comment.create])
|
90
|
+
@guilherme.update_attributes(:comments => [Comment.create, Comment.create, Comment.create])
|
91
|
+
post = Post.where { comments >= 2 }.first
|
92
|
+
assert_equal @caelum, post
|
93
|
+
end
|
94
|
+
|
95
|
+
test "exists posts using range expectations" do
|
96
|
+
@caelum.update_attributes :published_at => 1.year.ago
|
97
|
+
|
98
|
+
posts = Post.where { published_at.between(2.years.ago, 6.months.ago) }
|
99
|
+
assert_equal @caelum, posts[0]
|
100
|
+
assert_equal 1, posts.size
|
101
|
+
end
|
102
|
+
|
103
|
+
test "accepts two conditions inline" do
|
104
|
+
@caelum.update_attributes :published_at => 1.year.ago
|
105
|
+
@guilherme.update_attributes :published_at => 1.year.ago
|
106
|
+
|
107
|
+
posts = Post.where {
|
108
|
+
published_at.between(2.years.ago, 6.months.ago)
|
109
|
+
body.like?("%lum%")
|
110
|
+
}
|
111
|
+
assert_equal @caelum, posts[0]
|
112
|
+
assert_equal 1, posts.size
|
113
|
+
end
|
114
|
+
|
115
|
+
test "supports two conditions in dsl mixing everything together" do
|
116
|
+
@caelum.update_attributes(:comments => [Comment.create, Comment.create])
|
117
|
+
@guilherme.update_attributes(:comments => [Comment.create, Comment.create, Comment.create])
|
118
|
+
posts = Post.where { comments >= 1 }.where(:body).like?("%lum%")
|
119
|
+
assert_equal @caelum, posts[0]
|
120
|
+
assert_equal 1, posts.size
|
121
|
+
end
|
122
|
+
|
123
|
+
test "supports == with relation count" do
|
124
|
+
@caelum.update_attributes(:comments => [Comment.create, Comment.create])
|
125
|
+
posts = Post.where { comments == 2 }
|
126
|
+
assert_equal @caelum, posts[0]
|
127
|
+
assert_equal 1, posts.size
|
128
|
+
end
|
129
|
+
|
130
|
+
test "supports == with simple field" do
|
131
|
+
posts = Post.where { body == "CaelumObjects training and inovation" }
|
132
|
+
assert_equal @caelum, posts[0]
|
133
|
+
assert_equal 1, posts.size
|
134
|
+
end
|
135
|
+
|
136
|
+
test "supports != with simple field" do
|
137
|
+
posts = Post.where { body != "diff" }
|
138
|
+
assert_equal @caelum, posts[0]
|
139
|
+
assert_equal @guilherme, posts[1]
|
87
140
|
assert_equal 2, posts.size
|
88
141
|
end
|
89
142
|
|
90
|
-
test "
|
143
|
+
test "accepts two conditions one after the other" do
|
91
144
|
@caelum.update_attributes :published_at => 1.year.ago
|
145
|
+
@guilherme.update_attributes :published_at => 1.year.ago
|
92
146
|
|
93
147
|
posts = Post.where { published_at.between(2.years.ago, 6.months.ago) }
|
94
148
|
assert_equal @caelum, posts[0]
|
149
|
+
assert_equal 2, posts.size
|
150
|
+
posts = posts.where { body.like?("%lum%") }
|
151
|
+
assert_equal @caelum, posts[0]
|
95
152
|
assert_equal 1, posts.size
|
96
153
|
end
|
97
154
|
|
98
|
-
test "
|
99
|
-
|
100
|
-
@caelum.update_attributes :comments => [comment]
|
101
|
-
posts = Post.where(:comments).subject.like?("%dsl subject%")
|
155
|
+
test "accepts any custom condition" do
|
156
|
+
posts = Post.where { body "like ?", "%lum%" }
|
102
157
|
assert_equal @caelum, posts[0]
|
103
158
|
assert_equal 1, posts.size
|
104
159
|
end
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
160
|
+
|
161
|
+
test "give records with nil fields" do
|
162
|
+
@caelum.update_attributes :body => nil
|
163
|
+
posts = Post.where(:body).is_null
|
164
|
+
assert_equal @caelum, posts[0]
|
165
|
+
assert_equal 1, posts.size
|
166
|
+
end
|
167
|
+
|
168
|
+
|
169
|
+
# test "second level relation in a dsl" do
|
170
|
+
# comment = Comment.create :description => "dsl test"
|
171
|
+
# @caelum.update_attributes :comments => [comment]
|
172
|
+
#
|
173
|
+
# posts = Post.where{ comments.description.like?("%dsl test%") }
|
113
174
|
# assert_equal @caelum, posts[0]
|
114
175
|
# assert_equal 1, posts.size
|
176
|
+
#
|
115
177
|
# end
|
116
178
|
|
117
|
-
# def pending
|
118
|
-
# support .all, .first, and so on
|
119
|
-
# posts = Post.where { comments.description.like?("%dsl test%") }
|
120
|
-
# posts = posts.and(:authors).count.lt(3)
|
121
179
|
# Author.where(:posts).comments.count.gt(2)
|
122
|
-
|
123
|
-
|
180
|
+
|
124
181
|
end
|
@@ -1,55 +1,55 @@
|
|
1
1
|
require File.expand_path(File.dirname(__FILE__)) + "/test_helper"
|
2
2
|
|
3
|
-
require '
|
3
|
+
require 'relata/filter'
|
4
4
|
require 'schema'
|
5
5
|
|
6
6
|
class FilteredRelationTest < ActiveSupport::TestCase
|
7
7
|
setup do
|
8
8
|
setup_db
|
9
9
|
create_posts
|
10
|
+
end
|
11
|
+
|
12
|
+
test "given no values to filtered_relation, gives us all records" do
|
13
|
+
assert_equal Post.all, Post.filtered_relation({}).all
|
14
|
+
end
|
15
|
+
|
16
|
+
test "given a content and comment filter, gives us filtered records - generic" do
|
17
|
+
@base.update_attributes(:content => "picture", :comments => [Comment.create])
|
18
|
+
assert_equal @base, Post.filtered_relation(:content => "picture", :comments => 'true').first
|
10
19
|
end
|
11
20
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
21
|
+
test "given a content and comment filter, gives us filtered records" do
|
22
|
+
@base.update_attributes(:content => "picture", :comments => [Comment.create])
|
23
|
+
assert_equal @base, Post.filtered_relation(:content => "picture").related_to(:comments => true).first
|
24
|
+
end
|
25
|
+
|
26
|
+
test "given a date and comment filter, gives us filtered records" do
|
27
|
+
@base.update_attributes(:published_at => 2.years.ago, :comments => [Comment.create])
|
28
|
+
assert_equal @base, Post.filtered_relation(:published_at => true).related_to(:comments => true).first
|
29
|
+
end
|
30
|
+
|
31
|
+
test "given a date and content filter, gives us filtered records" do
|
32
|
+
@base.update_attribute(:published_at, 2.years.ago)
|
33
|
+
@base.update_attribute(:content, "picture")
|
34
|
+
record = Post.filtered_relation(:published_at => true, :content => "picture").first
|
25
35
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
36
|
+
assert_equal @base, record
|
37
|
+
end
|
38
|
+
|
39
|
+
test "given two dates, gives us filtered records between this date" do
|
40
|
+
assert_equal @base, Post.date_between(:before => 1.year.ago, :after => Time.now).first
|
41
|
+
end
|
42
|
+
|
43
|
+
test "return a post with same title" do
|
44
|
+
@base.update_attributes(:title => "Post Title")
|
45
|
+
assert_equal @base, Post.filtered_relation(:title => "Post Title").first
|
46
|
+
end
|
47
|
+
|
48
|
+
test "return a post with same title and body" do
|
49
|
+
@base.update_attributes(:title => "Post Title", :body => "Ruby")
|
50
|
+
assert_equal @base, Post.filtered_relation(:title => "Post Title", :body => "Ruby").first
|
51
|
+
end
|
35
52
|
|
36
|
-
assert_equal @base, record
|
37
|
-
end
|
38
|
-
|
39
|
-
test "given two dates, gives us filtered records between this date" do
|
40
|
-
assert_equal @base, Post.date_between(:before => 1.year.ago, :after => Time.now).first
|
41
|
-
end
|
42
|
-
|
43
|
-
test "return a post with same title" do
|
44
|
-
@base.update_attributes(:title => "Post Title")
|
45
|
-
assert_equal @base, Post.filtered_relation(:title => "Post Title").first
|
46
|
-
end
|
47
|
-
|
48
|
-
test "return a post with same title and body" do
|
49
|
-
@base.update_attributes(:title => "Post Title", :body => "Ruby")
|
50
|
-
assert_equal @base, Post.filtered_relation(:title => "Post Title", :body => "Ruby").first
|
51
|
-
end
|
52
|
-
|
53
53
|
|
54
54
|
def create_posts
|
55
55
|
valid_attributes = {
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__)) + "/test_helper"
|
2
|
+
require 'schema'
|
3
|
+
require 'relata/dsl'
|
4
|
+
|
5
|
+
class DSLTest < ActiveSupport::TestCase
|
6
|
+
|
7
|
+
setup do
|
8
|
+
setup_db
|
9
|
+
@caelum = Post.create :body => "CaelumObjects training and inovation"
|
10
|
+
@guilherme = Post.create :body => "Guilherme Silveira"
|
11
|
+
end
|
12
|
+
|
13
|
+
test "all post which commits has some subject" do
|
14
|
+
comment = Comment.create :subject => "dsl subject"
|
15
|
+
@caelum.update_attributes :comments => [comment]
|
16
|
+
posts = Post.where(:comments).subject.like?("%dsl subject%")
|
17
|
+
assert_equal @caelum, posts[0]
|
18
|
+
assert_equal 1, posts.size
|
19
|
+
end
|
20
|
+
|
21
|
+
test "all post which commits has some description" do
|
22
|
+
comment = Comment.create :description => "dsl test"
|
23
|
+
@caelum.update_attributes :comments => [comment]
|
24
|
+
|
25
|
+
posts = Post.where(:comments).description.like?("%dsl test%")
|
26
|
+
assert_equal @caelum, posts[0]
|
27
|
+
assert_equal 1, posts.size
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
test "all post which commits has some subject and another has_many relation" do
|
32
|
+
reader = Reader.create :name => "anderson"
|
33
|
+
comment = Comment.create :subject => "dsl subject"
|
34
|
+
@caelum.update_attributes :comments => [comment], :readers => [reader]
|
35
|
+
posts = Post.where(:comments).subject.like?("%dsl subject%")
|
36
|
+
assert_equal @caelum, posts[0]
|
37
|
+
assert_equal 1, posts.size
|
38
|
+
end
|
39
|
+
|
40
|
+
test "exists posts for a specific user name" do
|
41
|
+
user = User.create :name => "anderson"
|
42
|
+
@caelum.update_attributes(:user => user)
|
43
|
+
posts = Post.where(:user).name.like?("anderson")
|
44
|
+
assert_equal @caelum, posts[0]
|
45
|
+
assert_equal 1, posts.size
|
46
|
+
end
|
47
|
+
|
48
|
+
test "exists posts for a specific user title" do
|
49
|
+
user = User.create :title => "programmer"
|
50
|
+
@caelum.update_attributes(:user => user)
|
51
|
+
posts = Post.where(:user).title.like?("programmer")
|
52
|
+
assert_equal @caelum, posts[0]
|
53
|
+
assert_equal 1, posts.size
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
end
|
data/test/schema.rb
CHANGED
@@ -20,6 +20,8 @@ def setup_db
|
|
20
20
|
end
|
21
21
|
|
22
22
|
create_table :users do |t|
|
23
|
+
t.string :name
|
24
|
+
t.text :title
|
23
25
|
t.timestamps
|
24
26
|
end
|
25
27
|
|
@@ -29,6 +31,13 @@ def setup_db
|
|
29
31
|
t.integer :post_id
|
30
32
|
t.timestamps
|
31
33
|
end
|
34
|
+
|
35
|
+
create_table :readers do |t|
|
36
|
+
t.text :name
|
37
|
+
t.integer :post_id
|
38
|
+
t.timestamps
|
39
|
+
end
|
40
|
+
|
32
41
|
|
33
42
|
end
|
34
43
|
end
|
@@ -36,6 +45,7 @@ end
|
|
36
45
|
class Post < ActiveRecord::Base
|
37
46
|
belongs_to :user
|
38
47
|
has_many :comments
|
48
|
+
has_many :readers
|
39
49
|
end
|
40
50
|
|
41
51
|
class User < ActiveRecord::Base
|
@@ -46,3 +56,7 @@ class Comment < ActiveRecord::Base
|
|
46
56
|
belongs_to :post
|
47
57
|
end
|
48
58
|
|
59
|
+
class Reader < ActiveRecord::Base
|
60
|
+
belongs_to :post
|
61
|
+
end
|
62
|
+
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 3
|
9
|
+
version: 0.0.3
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Anderson Leite, Guilherme Silveira
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2010-10-
|
17
|
+
date: 2010-10-05 00:00:00 -03:00
|
18
18
|
default_executable:
|
19
19
|
dependencies: []
|
20
20
|
|
@@ -35,17 +35,22 @@ files:
|
|
35
35
|
- README.markdown
|
36
36
|
- test.sqlite3
|
37
37
|
- uninstall.rb
|
38
|
-
- lib/
|
39
|
-
- lib/
|
40
|
-
- lib/
|
41
|
-
- lib/
|
42
|
-
- lib/
|
43
|
-
- lib/
|
44
|
-
- lib/
|
45
|
-
- lib/
|
46
|
-
- lib/
|
38
|
+
- lib/relata/dsl/conditions.rb
|
39
|
+
- lib/relata/dsl/constraints.rb
|
40
|
+
- lib/relata/dsl/custom_relation.rb
|
41
|
+
- lib/relata/dsl/field_search.rb
|
42
|
+
- lib/relata/dsl/missed_builder.rb
|
43
|
+
- lib/relata/dsl/querys/belongs.rb
|
44
|
+
- lib/relata/dsl/querys/fields.rb
|
45
|
+
- lib/relata/dsl/querys/multiple.rb
|
46
|
+
- lib/relata/dsl/querys/simple.rb
|
47
|
+
- lib/relata/dsl.rb
|
48
|
+
- lib/relata/filter.rb
|
49
|
+
- lib/relata/related_query_methods.rb
|
50
|
+
- lib/relata.rb
|
47
51
|
- test/dsl_test.rb
|
48
52
|
- test/filtered_relation_test.rb
|
53
|
+
- test/relation_dsl_test.rb
|
49
54
|
- test/schema.rb
|
50
55
|
- test/test_helper.rb
|
51
56
|
has_rdoc: true
|
data/lib/filtered_relation.rb
DELETED
@@ -1,109 +0,0 @@
|
|
1
|
-
require 'filtered_relation/dsl/conditions'
|
2
|
-
require 'filtered_relation/dsl/constraints'
|
3
|
-
require 'filtered_relation/dsl/querys/multiple'
|
4
|
-
require 'filtered_relation/dsl/querys/simple'
|
5
|
-
require 'filtered_relation/dsl/querys/fields'
|
6
|
-
|
7
|
-
# in case you did not require the entire filtered_relation plugin
|
8
|
-
module FilteredRelation
|
9
|
-
module Dsl
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
|
-
# defines helper methods to deal with custom relation
|
14
|
-
module FilteredRelation::Dsl::CustomRelation
|
15
|
-
include Conditions
|
16
|
-
include Constraints
|
17
|
-
|
18
|
-
def using(record, field)
|
19
|
-
@record = record
|
20
|
-
@current_field = field
|
21
|
-
@start_field = field
|
22
|
-
@select_fields = ["#{table_name}.*"]
|
23
|
-
@groups = []
|
24
|
-
if relates_to_many?
|
25
|
-
self.extend MultipleQuery
|
26
|
-
self.extend ModelFields
|
27
|
-
else
|
28
|
-
self.extend SimpleQuery
|
29
|
-
end
|
30
|
-
|
31
|
-
self
|
32
|
-
end
|
33
|
-
|
34
|
-
private
|
35
|
-
|
36
|
-
def relates_to_many?
|
37
|
-
@record.reflect_on_association @current_field.to_sym
|
38
|
-
end
|
39
|
-
|
40
|
-
end
|
41
|
-
|
42
|
-
# a relation search in a specific field
|
43
|
-
class FilteredRelation::Dsl::FieldSearch
|
44
|
-
|
45
|
-
def initialize(rel, field)
|
46
|
-
@rel = rel
|
47
|
-
@field = field
|
48
|
-
end
|
49
|
-
|
50
|
-
def >=(value)
|
51
|
-
@rel.where(@field).count.ge(value)
|
52
|
-
end
|
53
|
-
|
54
|
-
def like?(value)
|
55
|
-
@rel.where(@field).like?(value)
|
56
|
-
end
|
57
|
-
|
58
|
-
def exists?
|
59
|
-
@rel.where(@field).exists?
|
60
|
-
end
|
61
|
-
|
62
|
-
def between(first, second)
|
63
|
-
@rel.where("#{@field} > ? and #{@field} < ?", first, second)
|
64
|
-
end
|
65
|
-
|
66
|
-
end
|
67
|
-
|
68
|
-
# a builder ready to collect which field you want to search
|
69
|
-
class FilteredRelation::Dsl::MissedBuilder
|
70
|
-
|
71
|
-
def initialize(rel)
|
72
|
-
@rel = rel
|
73
|
-
end
|
74
|
-
|
75
|
-
def method_missing(field, *args)
|
76
|
-
if args.size != 0
|
77
|
-
raise "Unable to setup a parameter with args: #{field} and #{args}"
|
78
|
-
end
|
79
|
-
FilteredRelation::Dsl::FieldSearch.new(@rel, field)
|
80
|
-
end
|
81
|
-
|
82
|
-
end
|
83
|
-
|
84
|
-
module FilteredRelation::Dsl::Relation
|
85
|
-
|
86
|
-
# extended where clause that allows symbol and custom dsl lookup
|
87
|
-
#
|
88
|
-
# examples:
|
89
|
-
# where(:body).like?("%guilherme%")
|
90
|
-
# where { body.like?("%guilherme%")
|
91
|
-
#
|
92
|
-
# While the last will delegate to the MissedBuilder component
|
93
|
-
# the symbol based query will delegate query builder to CustomRelation.
|
94
|
-
def where(*args, &block)
|
95
|
-
if args.size==0 && block
|
96
|
-
FilteredRelation::Dsl::MissedBuilder.new(self).instance_eval(&block)
|
97
|
-
elsif args.size==1 && args[0].is_a?(Symbol)
|
98
|
-
relation = scoped
|
99
|
-
relation.extend FilteredRelation::Dsl::CustomRelation
|
100
|
-
relation.using(self, args[0])
|
101
|
-
else
|
102
|
-
super(*args, &block)
|
103
|
-
end
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
class ActiveRecord::Relation
|
108
|
-
include FilteredRelation::Dsl::Relation
|
109
|
-
end
|
@@ -1,36 +0,0 @@
|
|
1
|
-
# A custom set of conditions that can be applied
|
2
|
-
# to a query
|
3
|
-
module Conditions
|
4
|
-
def ge(value)
|
5
|
-
add_filter(">= #{value}")
|
6
|
-
end
|
7
|
-
|
8
|
-
def greater_or_equals(value)
|
9
|
-
ge(value)
|
10
|
-
end
|
11
|
-
|
12
|
-
def gt(value)
|
13
|
-
add_filter("> #{value}")
|
14
|
-
end
|
15
|
-
|
16
|
-
def greater_than(value)
|
17
|
-
gt(value)
|
18
|
-
end
|
19
|
-
|
20
|
-
def lt(value)
|
21
|
-
add_filter("< #{value}")
|
22
|
-
end
|
23
|
-
|
24
|
-
def lesser_than(value)
|
25
|
-
lt value
|
26
|
-
end
|
27
|
-
|
28
|
-
# whether this relation has at least one element.
|
29
|
-
def exists?
|
30
|
-
if @relation_search.nil?
|
31
|
-
count.exists?
|
32
|
-
else
|
33
|
-
add_filter("> 0")
|
34
|
-
end
|
35
|
-
end
|
36
|
-
end
|