relata 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/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :gemcutter
2
+ gem 'sqlite3-ruby', :require => 'sqlite3'
3
+ gem 'ruby-debug19', :require => "ruby-debug"
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2010 [name of plugin creator]
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.markdown ADDED
@@ -0,0 +1,43 @@
1
+ #FilteredRelation#
2
+
3
+ Making dynamic filters easier with a nice ActiveRecord DSL.
4
+
5
+ ## Filter Example ##
6
+
7
+ Create dynamic filters with just onde method.
8
+
9
+ <% form_tag :action => 'filter' do %>
10
+ Title: <%= text_field_tag 'post[title]' %><br />
11
+ Only with Comments?
12
+ <%= select("post", "comments", options_for_select({ "false" => "", "true" => "true" })) %> %>
13
+
14
+ def filter
15
+ @posts = Post.filtered_relation(params[:post]).all
16
+ end
17
+
18
+ Create more advanced relations.
19
+
20
+ posts = Post.filtered_relation(:comments => true).where(:user_id => 4).limit(3).order("id ASC") 



21
+
22
+ posts.each do |post| 

23
+ # records
24
+ end 

25
+
26
+ ## DSL API ##
27
+
28
+ Post.where(:body).like?("%caelum%")
29
+
30
+ Post.where(:comments).count.exists?
31
+
32
+ Post.where(:comments).count.gt(2)
33
+
34
+ Post.where(:comments).count.lt(2)
35
+
36
+ Post.where(:comments).description.like?("%filtered%")
37
+
38
+ Post.where(:comments).subject.like?("%filtered%")
39
+
40
+ Post.where { comments >= 2 }
41
+
42
+ Post.where { published_at.between(2.years.ago, 6.months.ago) }
43
+
data/Rakefile ADDED
@@ -0,0 +1,45 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ require 'rake/gempackagetask'
5
+
6
+ desc 'Default: run unit tests.'
7
+ task :default => :test
8
+
9
+ desc 'Test the relata plugin.'
10
+ Rake::TestTask.new(:test) do |t|
11
+ t.libs << 'lib'
12
+ t.libs << 'test'
13
+ t.pattern = 'test/**/*_test.rb'
14
+ t.verbose = true
15
+ end
16
+
17
+ desc 'Generate documentation for the relata plugin.'
18
+ Rake::RDocTask.new(:rdoc) do |rdoc|
19
+ rdoc.rdoc_dir = 'rdoc'
20
+ rdoc.title = 'relata'
21
+ rdoc.options << '--line-numbers' << '--inline-source'
22
+ rdoc.rdoc_files.include('README.markdown')
23
+ rdoc.rdoc_files.include('lib/**/*.rb')
24
+ end
25
+
26
+ PKG_FILES = FileList[ '[a-zA-Z]*', 'generators/**/*', 'lib/**/*', 'rails/**/*', 'tasks/**/*', 'test/**/*' ]
27
+
28
+ spec = Gem::Specification.new do |s|
29
+ s.name = "relata"
30
+ s.version = "0.0.3"
31
+ s.author = "Anderson Leite, Guilherme Silveira"
32
+ s.email = "anderson.leite@caelum.com.br"
33
+ s.homepage = "http://github.com/caelum/relata"
34
+ s.platform = Gem::Platform::RUBY
35
+ s.summary = "Helps poking around with relationships when using ARel"
36
+ s.files = PKG_FILES.to_a
37
+ s.require_path = "lib"
38
+ s.has_rdoc = false
39
+ s.extra_rdoc_files = ["README.markdown"]
40
+ end
41
+
42
+ desc 'Turn this plugin into a gem.'
43
+ Rake::GemPackageTask.new(spec) do |pkg|
44
+ pkg.gem_spec = spec
45
+ end
data/init.rb ADDED
@@ -0,0 +1,7 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), "lib"))
2
+
3
+ require 'ruby-debug'
4
+ require 'active_record'
5
+ require "active_support"
6
+
7
+ require "filtered_relation"
data/install.rb ADDED
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,3 @@
1
+ module FilteredRelation
2
+ require 'filtered_relation/filter'
3
+ end
@@ -0,0 +1,45 @@
1
+ # A custom set of conditions that can be applied
2
+ # to a query
3
+ module Relata::Dsl::Conditions
4
+
5
+ def eq(value)
6
+ add_filter("= #{value}")
7
+ end
8
+
9
+ def ge(value)
10
+ add_filter(">= #{value}")
11
+ end
12
+
13
+ def greater_or_equals(value)
14
+ ge(value)
15
+ end
16
+
17
+ def gt(value)
18
+ add_filter("> #{value}")
19
+ end
20
+
21
+ def greater_than(value)
22
+ gt(value)
23
+ end
24
+
25
+ def le(value)
26
+ add_filter("<= #{value}")
27
+ end
28
+
29
+ def lt(value)
30
+ add_filter("< #{value}")
31
+ end
32
+
33
+ def lesser_than(value)
34
+ lt value
35
+ end
36
+
37
+ # whether this relation has at least one element.
38
+ def exists?
39
+ if @relation_search.nil?
40
+ count.exists?
41
+ else
42
+ add_filter("> 0")
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,62 @@
1
+ module Relata::Dsl::Constraints
2
+
3
+ def length
4
+ @relation_search = LengthManager
5
+ self
6
+ end
7
+
8
+ class LengthManager
9
+ def self.condition(field, *args)
10
+ "len(field)"
11
+ end
12
+ end
13
+
14
+ def count
15
+ @select_fields << "COUNT(#{@current_field}.id) AS count"
16
+ @groups << "#{table_name}.id"
17
+ @relation_search = 'count'
18
+ self
19
+ end
20
+
21
+ def like?(value)
22
+ query.where("#{@current_field} like ?", [value])
23
+ end
24
+
25
+ # def between(first, second)
26
+ # @relation_search = SimpleRangeCondition
27
+ # self
28
+ # # query.where("#{@current_field} like ?", [value])
29
+ # # add_filter("> #{first}").add_filter("< #{second}")
30
+ # end
31
+
32
+ class SimpleCondition
33
+ def self.condition(field, *args)
34
+ "#{field}"
35
+ end
36
+ end
37
+
38
+ class SimpleRangeCondition
39
+ def self.condition(field, *args)
40
+ "#{field} > #{args[0]} AND #{field} < #{args[1]}"
41
+ end
42
+ end
43
+
44
+ class RangeManager
45
+ def self.select_fields(facet)
46
+ "COUNT(#{facet}.id) AS count"
47
+ end
48
+ def self.having(expectation)
49
+ "count #{expectation}"
50
+ end
51
+ end
52
+
53
+ class CountManager
54
+ def self.select_fields(facet)
55
+ "COUNT(#{facet}.id) AS count"
56
+ end
57
+ def self.having(expectation)
58
+ "count #{expectation}"
59
+ end
60
+ end
61
+
62
+ end
@@ -0,0 +1,26 @@
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
+ if relates_to_many?
13
+ self.extend MultipleQuery
14
+ self.extend ModelFields
15
+ else
16
+ self.extend SimpleQuery
17
+ end
18
+
19
+ self
20
+ end
21
+
22
+ def relates_to_many?
23
+ @record.reflect_on_association @current_field.to_sym
24
+ end
25
+
26
+ end
@@ -0,0 +1,85 @@
1
+ # a relation search in a specific field
2
+ class Relata::Dsl::FieldSearch
3
+
4
+ def initialize(rel, field)
5
+ @rel = rel
6
+ @field = field
7
+ end
8
+
9
+ def ==(value)
10
+ @rel.where("#{@field} == ?", value)
11
+ end
12
+
13
+ def >=(value)
14
+ @rel.where("#{@field} >= ?", value)
15
+ end
16
+
17
+ def <=(value)
18
+ @rel.where("#{@field} <= ?", value)
19
+ end
20
+
21
+ def >(value)
22
+ @rel.where("#{@field} > ?", value)
23
+ end
24
+
25
+ def <(value)
26
+ @rel.where("#{@field} < ?", value)
27
+ end
28
+
29
+ def like?(value)
30
+ @rel.where(@field).like?(value)
31
+ end
32
+
33
+ def between(first, second)
34
+ @rel.where("#{@field} > ? and #{@field} < ?", first, second)
35
+ end
36
+
37
+ def length
38
+ @field = "length(#{@field})"
39
+ self
40
+ end
41
+
42
+ def custom(*args)
43
+ comparison = args.shift
44
+ @rel.where("#{@field} #{comparison}", args)
45
+ end
46
+
47
+ end
48
+
49
+ class Relata::Dsl::FieldSearchMany
50
+
51
+ def initialize(rel, field)
52
+ @rel = rel
53
+ @field = field
54
+ end
55
+
56
+ def ==(value)
57
+ @rel.where(@field).count.eq(value)
58
+ end
59
+
60
+ def >=(value)
61
+ @rel.where(@field).count.ge(value)
62
+ end
63
+
64
+ def <=(value)
65
+ @rel.where(@field).count.le(value)
66
+ end
67
+
68
+ def >(value)
69
+ @rel.where(@field).count.gt(value)
70
+ end
71
+
72
+ def <(value)
73
+ @rel.where(@field).count.lt(value)
74
+ end
75
+
76
+ def exists?
77
+ @rel.where(@field).exists?
78
+ end
79
+
80
+ def custom(*args)
81
+ comparison = args.shift
82
+ @rel.where("#{@field} #{comparison}", args)
83
+ end
84
+
85
+ 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,25 @@
1
+ module ModelFields
2
+
3
+ def self.extended(base)
4
+
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
8
+ end
9
+ end
10
+
11
+ @fields.each do |field|
12
+ include_method field if field != nil
13
+ end
14
+
15
+ end
16
+
17
+ private
18
+ def self.include_method(field)
19
+ define_method field do
20
+ @current_field = "#{@current_field}.#{field}"
21
+ self
22
+ end
23
+ end
24
+
25
+ end
@@ -0,0 +1,8 @@
1
+ module MultipleQuery
2
+ def query
3
+ preload(@start_field).select(@select_fields.join ',').from("#{table_name}, #{@start_field}").where("#{table_name}.id = #{@start_field}.post_id")
4
+ end
5
+ def add_filter expectation
6
+ query.group(@groups.first).having("#{@relation_search} #{expectation}")
7
+ end
8
+ end
@@ -0,0 +1,11 @@
1
+ module SimpleQuery
2
+ def query
3
+ self
4
+ end
5
+
6
+ def add_filter *expectation
7
+ base = @relation_search.condition(@current_field.to_s, expectation)
8
+ where("#{base} #{expectation}")
9
+ end
10
+
11
+ end
data/lib/relata/dsl.rb ADDED
@@ -0,0 +1,41 @@
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
+
16
+ module Relata::Dsl::Relation
17
+
18
+ # extended where clause that allows symbol and custom dsl lookup
19
+ #
20
+ # examples:
21
+ # where(:body).like?("%guilherme%")
22
+ # where { body.like?("%guilherme%")
23
+ #
24
+ # While the last will delegate to the MissedBuilder component
25
+ # the symbol based query will delegate query builder to CustomRelation.
26
+ def where(*args, &block)
27
+ if args.size==0 && block
28
+ Relata::Dsl::MissedBuilder.new(self).instance_eval(&block)
29
+ elsif args.size==1 && args[0].is_a?(Symbol)
30
+ relation = scoped
31
+ relation.extend Relata::Dsl::CustomRelation
32
+ relation.using(self, args[0])
33
+ else
34
+ super(*args, &block)
35
+ end
36
+ end
37
+ end
38
+
39
+ class ActiveRecord::Relation
40
+ include Relata::Dsl::Relation
41
+ end
@@ -0,0 +1,46 @@
1
+ require 'filtered_relation/related_query_methods'
2
+ ActiveRecord::Base.send :include, RelatedQueryMethods
3
+
4
+ module FilteredRelation
5
+
6
+ class ::ActiveRecord::Base
7
+
8
+ def self.filtered_relation(params)
9
+ relation = scoped
10
+
11
+ columns = self.columns.map do |c|
12
+ c.name if [:string, :text].include? c.type
13
+ end
14
+
15
+ params.each do |facet, value|
16
+ if self.reflect_on_association facet.to_sym
17
+ relation = send("filter_by_has_many", facet, value, relation)
18
+ elsif columns.include? facet.to_s
19
+ relation = send("filter_by_exact", facet, value, relation)
20
+ else
21
+ relation = send("filter_by_#{facet}", value, relation)
22
+ end
23
+ end
24
+
25
+ relation
26
+ end
27
+
28
+ def self.related_to(params)
29
+ relation = scoped
30
+
31
+ params.each do |facet, value|
32
+ relation = send("filter_by_related", facet, value, relation)
33
+ end
34
+ relation
35
+ end
36
+
37
+ def self.date_between(params)
38
+ relation = scoped
39
+ relation = send("filter_by_date_between", params, relation)
40
+ relation
41
+ end
42
+
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,44 @@
1
+ module RelatedQueryMethods
2
+
3
+ def self.included(base)
4
+ base.extend ClassMethods
5
+ end
6
+
7
+ module ClassMethods
8
+
9
+ def filter_by_has_many(facet, value, relation)
10
+
11
+ table_name = self.table_name
12
+
13
+ if !value.empty?
14
+ relation.preload(facet).select("#{table_name}.*, COUNT(#{facet}.id) AS count").from("#{table_name}, #{facet}").where("#{table_name}.id = #{facet}.post_id").group("#{table_name}.id").having("count > 0")
15
+ else
16
+ relation
17
+ end
18
+ end
19
+
20
+ def filter_by_related(facet, value, relation)
21
+ if value
22
+ relation.preload(facet).select("posts.*, COUNT(#{facet}.id) AS comment_count").from("posts, #{facet}").group("posts.id").having("comment_count > 0")
23
+ else
24
+ relation
25
+ end
26
+ end
27
+
28
+ def filter_by_exact(facet, value, relation)
29
+ !value.empty? ? relation.where(facet => value) : relation
30
+ end
31
+
32
+ def filter_by_published_at(value, relation)
33
+ value ? relation.where("published_at < ?", 1.month.ago) : relation
34
+ end
35
+
36
+ def filter_by_date_between(params, relation)
37
+ relation.where("published_at < ?", params[:before])
38
+ relation.where("published_at > ?", params[:after])
39
+ relation
40
+ end
41
+
42
+ end
43
+
44
+ end
data/test/dsl_test.rb ADDED
@@ -0,0 +1,187 @@
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 "given an attribute and expectation, gives the results" do
14
+ posts = Post.where(:body).like?("%caelum%").all
15
+ assert_equal @caelum, posts[0]
16
+ assert_equal 1, posts.size
17
+
18
+ posts = Post.where { body.like? "%caelum%" }
19
+ assert_equal @caelum, posts[0]
20
+ assert_equal 1, posts.size
21
+ end
22
+
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
+
29
+ test "exists posts with comments" do
30
+ @caelum.update_attributes(:comments => [Comment.create])
31
+ posts = Post.where(:comments).count.exists?
32
+ assert_equal @caelum, posts[0]
33
+ assert_equal 1, posts.size
34
+ end
35
+
36
+ test "exists posts with comments can be shortcuted with exists?" do
37
+ @caelum.update_attributes(:comments => [Comment.create])
38
+ posts = Post.where(:comments).exists?
39
+ assert_equal @caelum, posts[0]
40
+ assert_equal 1, posts.size
41
+
42
+ posts = Post.where { comments.exists? }
43
+ assert_equal @caelum, posts[0]
44
+ assert_equal 1, posts.size
45
+ end
46
+
47
+ test "exists posts with more than 2 comments" do
48
+ @caelum.update_attributes(:comments => [Comment.create, Comment.create, Comment.create])
49
+ posts = Post.where(:comments).count.gt(2)
50
+ assert_equal @caelum, posts.first
51
+ assert_equal 3, posts.first.comments.size
52
+ end
53
+
54
+ test "exists posts with less than 2 comments" do
55
+ @caelum.update_attributes(:comments => [Comment.create])
56
+ posts = Post.where(:comments).count.lt(2)
57
+ assert_equal @caelum, posts.first
58
+ assert_equal 1, posts.first.comments.size
59
+ end
60
+
61
+ test "exists posts with more than or equals 2 comments" do
62
+ @caelum.update_attributes(:comments => [Comment.create, Comment.create])
63
+ @guilherme.update_attributes(:comments => [Comment.create, Comment.create, Comment.create])
64
+
65
+ posts = Post.where(:comments).count.ge(2).all
66
+ assert_equal 2, posts.size
67
+ assert_equal @caelum, posts[0]
68
+ assert_equal @guilherme, posts[1]
69
+ end
70
+
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
77
+ end
78
+
79
+ # pending
80
+ # test "all post which commits has some description" do
81
+ # comment = Comment.create :description => "dsl test"
82
+ # @caelum.update_attributes :comments => [comment]
83
+ #
84
+ # posts = Post.where(:comments).description.like?("%dsl test%")
85
+ # assert_equal @caelum, posts[0]
86
+ # assert_equal 1, posts.size
87
+ #
88
+ # end
89
+
90
+ test "exists posts using strict extended methods" do
91
+ @caelum.update_attributes(:comments => [Comment.create, Comment.create])
92
+ @guilherme.update_attributes(:comments => [Comment.create, Comment.create, Comment.create])
93
+ posts = Post.where { comments >= 2 }
94
+ assert_equal @caelum, posts[0]
95
+ assert_equal 2, posts.size
96
+ assert_equal @guilherme, posts[1]
97
+ end
98
+
99
+ test "strict block supports first" do
100
+ @caelum.update_attributes(:comments => [Comment.create, Comment.create])
101
+ @guilherme.update_attributes(:comments => [Comment.create, Comment.create, Comment.create])
102
+ post = Post.where { comments >= 2 }.first
103
+ assert_equal @caelum, post
104
+ end
105
+
106
+ test "exists posts using range expectations" do
107
+ @caelum.update_attributes :published_at => 1.year.ago
108
+
109
+ posts = Post.where { published_at.between(2.years.ago, 6.months.ago) }
110
+ assert_equal @caelum, posts[0]
111
+ assert_equal 1, posts.size
112
+ end
113
+
114
+ # pending
115
+ # test "all post which commits has some subject" do
116
+ # comment = Comment.create :subject => "dsl subject"
117
+ # @caelum.update_attributes :comments => [comment]
118
+ # posts = Post.where(:comments).subject.like?("%dsl subject%")
119
+ # assert_equal @caelum, posts[0]
120
+ # assert_equal 1, posts.size
121
+ # end
122
+
123
+ test "accepts two conditions inline" do
124
+ @caelum.update_attributes :published_at => 1.year.ago
125
+ @guilherme.update_attributes :published_at => 1.year.ago
126
+
127
+ posts = Post.where {
128
+ published_at.between(2.years.ago, 6.months.ago)
129
+ body.like?("%lum%")
130
+ }
131
+ assert_equal @caelum, posts[0]
132
+ assert_equal 1, posts.size
133
+ end
134
+
135
+ test "supports two conditions in dsl mixing everything together" do
136
+ @caelum.update_attributes(:comments => [Comment.create, Comment.create])
137
+ @guilherme.update_attributes(:comments => [Comment.create, Comment.create, Comment.create])
138
+ posts = Post.where { comments >= 1 }.where(:body).like?("%lum%")
139
+ assert_equal @caelum, posts[0]
140
+ assert_equal 1, posts.size
141
+ end
142
+
143
+ test "supports == with relation count" do
144
+ @caelum.update_attributes(:comments => [Comment.create, Comment.create])
145
+ posts = Post.where { comments == 2 }
146
+ assert_equal @caelum, posts[0]
147
+ assert_equal 1, posts.size
148
+ end
149
+
150
+ test "supports == with simple field" do
151
+ @caelum.update_attributes(:comments => [Comment.create, Comment.create])
152
+ posts = Post.where { body == "CaelumObjects training and inovation" }
153
+ assert_equal @caelum, posts[0]
154
+ assert_equal 1, posts.size
155
+ end
156
+
157
+ test "accepts two conditions one after the other" do
158
+ @caelum.update_attributes :published_at => 1.year.ago
159
+ @guilherme.update_attributes :published_at => 1.year.ago
160
+
161
+ posts = Post.where { published_at.between(2.years.ago, 6.months.ago) }
162
+ assert_equal @caelum, posts[0]
163
+ assert_equal 2, posts.size
164
+ posts = posts.where { body.like?("%lum%") }
165
+ assert_equal @caelum, posts[0]
166
+ assert_equal 1, posts.size
167
+ end
168
+
169
+ test "accepts any custom condition" do
170
+ posts = Post.where { body "like ?", "%lum%" }
171
+ assert_equal @caelum, posts[0]
172
+ assert_equal 1, posts.size
173
+ end
174
+
175
+ # test "second level relation in a dsl" do
176
+ # comment = Comment.create :description => "dsl test"
177
+ # @caelum.update_attributes :comments => [comment]
178
+ #
179
+ # posts = Post.where{ comments.description.like?("%dsl test%") }
180
+ # assert_equal @caelum, posts[0]
181
+ # assert_equal 1, posts.size
182
+ #
183
+ # end
184
+
185
+ # Author.where(:posts).comments.count.gt(2)
186
+
187
+ end
@@ -0,0 +1,75 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + "/test_helper"
2
+
3
+ require 'filtered_relation/filter'
4
+ require 'schema'
5
+
6
+ class FilteredRelationTest < ActiveSupport::TestCase
7
+ setup do
8
+ setup_db
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
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
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
35
+
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
+
54
+ def create_posts
55
+ valid_attributes = {
56
+ :body => "Hello.",
57
+ :title => "Hi!",
58
+ :content => "text",
59
+ :user_id => 1,
60
+ :published_at => Time.now
61
+ }
62
+
63
+ @base = Post.create(valid_attributes)
64
+ @quote = Post.create(valid_attributes.merge(:content => "quote"))
65
+ @number2 = Post.create(valid_attributes.merge(:user_id => 2))
66
+ @old = Post.create(valid_attributes.merge(:published_at => 1.year.ago))
67
+ end
68
+
69
+ teardown do
70
+ ActiveRecord::Base.connection.tables.each do |table|
71
+ ActiveRecord::Base.connection.drop_table(table)
72
+ end
73
+ end
74
+
75
+ end
data/test/schema.rb ADDED
@@ -0,0 +1,48 @@
1
+ require 'active_record'
2
+
3
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => "test.sqlite3")
4
+
5
+ def setup_db
6
+
7
+ ActiveRecord::Base.connection.tables.each do |table|
8
+ ActiveRecord::Base.connection.drop_table(table)
9
+ end
10
+
11
+ ActiveRecord::Schema.define(:version => 1) do
12
+
13
+ create_table :posts do |t|
14
+ t.string :body
15
+ t.string :title
16
+ t.text :content
17
+ t.integer :user_id
18
+ t.datetime :published_at
19
+ t.timestamps
20
+ end
21
+
22
+ create_table :users do |t|
23
+ t.timestamps
24
+ end
25
+
26
+ create_table :comments do |t|
27
+ t.text :subject
28
+ t.text :description
29
+ t.integer :post_id
30
+ t.timestamps
31
+ end
32
+
33
+ end
34
+ end
35
+
36
+ class Post < ActiveRecord::Base
37
+ belongs_to :user
38
+ has_many :comments
39
+ end
40
+
41
+ class User < ActiveRecord::Base
42
+ has_many :posts
43
+ end
44
+
45
+ class Comment < ActiveRecord::Base
46
+ belongs_to :post
47
+ end
48
+
data/test/test.sqlite3 ADDED
Binary file
@@ -0,0 +1,3 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'active_support'
data/test.sqlite3 ADDED
Binary file
data/uninstall.rb ADDED
@@ -0,0 +1 @@
1
+ # Uninstall hook code here
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: relata
3
+ version: !ruby/object:Gem::Version
4
+ hash: 25
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 3
10
+ version: 0.0.3
11
+ platform: ruby
12
+ authors:
13
+ - Anderson Leite, Guilherme Silveira
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2010-10-22 00:00:00 -02:00
19
+ default_executable:
20
+ dependencies: []
21
+
22
+ description:
23
+ email: anderson.leite@caelum.com.br
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files:
29
+ - README.markdown
30
+ files:
31
+ - Gemfile
32
+ - init.rb
33
+ - install.rb
34
+ - MIT-LICENSE
35
+ - Rakefile
36
+ - README.markdown
37
+ - test.sqlite3
38
+ - uninstall.rb
39
+ - lib/filtered_relation.rb
40
+ - lib/relata/dsl/conditions.rb
41
+ - lib/relata/dsl/constraints.rb
42
+ - lib/relata/dsl/custom_relation.rb
43
+ - lib/relata/dsl/field_search.rb
44
+ - lib/relata/dsl/missed_builder.rb
45
+ - lib/relata/dsl/querys/fields.rb
46
+ - lib/relata/dsl/querys/multiple.rb
47
+ - lib/relata/dsl/querys/simple.rb
48
+ - lib/relata/dsl.rb
49
+ - lib/relata/filter.rb
50
+ - lib/relata/related_query_methods.rb
51
+ - test/dsl_test.rb
52
+ - test/filtered_relation_test.rb
53
+ - test/schema.rb
54
+ - test/test.sqlite3
55
+ - test/test_helper.rb
56
+ has_rdoc: false
57
+ homepage: http://github.com/caelum/relata
58
+ licenses: []
59
+
60
+ post_install_message:
61
+ rdoc_options: []
62
+
63
+ require_paths:
64
+ - lib
65
+ required_ruby_version: !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ required_rubygems_version: !ruby/object:Gem::Requirement
75
+ none: false
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ hash: 3
80
+ segments:
81
+ - 0
82
+ version: "0"
83
+ requirements: []
84
+
85
+ rubyforge_project:
86
+ rubygems_version: 1.3.7
87
+ signing_key:
88
+ specification_version: 3
89
+ summary: Helps poking around with relationships when using ARel
90
+ test_files: []
91
+