relata 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
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
+