Relata 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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.2"
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
@@ -4,4 +4,4 @@ require 'ruby-debug'
4
4
  require 'active_record'
5
5
  require "active_support"
6
6
 
7
- require "filtered_relation"
7
+ require "relata"
@@ -0,0 +1,3 @@
1
+ module Relata
2
+ require 'relata/filter'
3
+ end
@@ -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
- module Constraints
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
- @fields = r.klass.columns.map do |c|
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
@@ -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
Binary file
@@ -1,6 +1,6 @@
1
1
  require File.expand_path(File.dirname(__FILE__)) + "/test_helper"
2
2
  require 'schema'
3
- require 'filtered_relation/dsl'
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
- # test "given an attribute and constraint expectation, gives the results" do
24
- # posts = Post.where { body < 22 }
25
- # assert_equal @guilherme, posts[0]
26
- # assert_equal 1, posts.size
27
- # end
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 "all post which commits has some description" do
72
- comment = Comment.create :description => "dsl test"
73
- @caelum.update_attributes :comments => [comment]
74
-
75
- posts = Post.where(:comments).description.like?("%dsl test%")
76
- assert_equal @caelum, posts[0]
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 "exists posts using range expectations" do
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 "all post which commits has some subject" do
99
- comment = Comment.create :subject => "dsl subject"
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
- # test "exists posts aaaaaaaaaaaaa" do
107
- # @caelum.update_attributes :published_at => 1.year.ago
108
- #
109
- # posts = Post.where {
110
- # published_at.between(2.years.ago, 6.months.ago)
111
- # name.like?
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
- # end
123
-
180
+
124
181
  end
@@ -1,55 +1,55 @@
1
1
  require File.expand_path(File.dirname(__FILE__)) + "/test_helper"
2
2
 
3
- require 'filtered_relation/filter'
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
- 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
19
- end
20
-
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
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
- 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
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
@@ -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
- - 2
9
- version: 0.0.2
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-04 00:00:00 -03:00
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/filtered_relation/dsl/conditions.rb
39
- - lib/filtered_relation/dsl/constraints.rb
40
- - lib/filtered_relation/dsl/querys/fields.rb
41
- - lib/filtered_relation/dsl/querys/multiple.rb
42
- - lib/filtered_relation/dsl/querys/simple.rb
43
- - lib/filtered_relation/dsl.rb
44
- - lib/filtered_relation/filter.rb
45
- - lib/filtered_relation/related_query_methods.rb
46
- - lib/filtered_relation.rb
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
@@ -1,3 +0,0 @@
1
- module FilteredRelation
2
- require 'filtered_relation/filter'
3
- end
@@ -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