Relata 0.0.2

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.2"
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,36 @@
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
@@ -0,0 +1,62 @@
1
+ module 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,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
@@ -0,0 +1,109 @@
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
@@ -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
@@ -0,0 +1,3 @@
1
+ module FilteredRelation
2
+ require 'filtered_relation/filter'
3
+ end
data/test/dsl_test.rb ADDED
@@ -0,0 +1,124 @@
1
+ require File.expand_path(File.dirname(__FILE__)) + "/test_helper"
2
+ require 'schema'
3
+ require 'filtered_relation/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 < 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)
66
+ assert_equal @caelum, posts[0]
67
+ assert_equal @guilherme, posts[1]
68
+ assert_equal 2, posts.size
69
+ end
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
+
79
+ end
80
+
81
+ test "exists posts using strict extended methods" do
82
+ @caelum.update_attributes(:comments => [Comment.create, Comment.create])
83
+ @guilherme.update_attributes(:comments => [Comment.create, Comment.create, Comment.create])
84
+ posts = Post.where { comments >= 2 }
85
+ assert_equal @caelum, posts[0]
86
+ assert_equal @guilherme, posts[1]
87
+ assert_equal 2, posts.size
88
+ end
89
+
90
+ test "exists posts using range expectations" do
91
+ @caelum.update_attributes :published_at => 1.year.ago
92
+
93
+ posts = Post.where { published_at.between(2.years.ago, 6.months.ago) }
94
+ assert_equal @caelum, posts[0]
95
+ assert_equal 1, posts.size
96
+ end
97
+
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%")
102
+ assert_equal @caelum, posts[0]
103
+ assert_equal 1, posts.size
104
+ 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
+ # }
113
+ # assert_equal @caelum, posts[0]
114
+ # assert_equal 1, posts.size
115
+ # end
116
+
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
+ # Author.where(:posts).comments.count.gt(2)
122
+ # end
123
+
124
+ 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
+
@@ -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,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: Relata
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 2
9
+ version: 0.0.2
10
+ platform: ruby
11
+ authors:
12
+ - Anderson Leite, Guilherme Silveira
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-10-04 00:00:00 -03:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description:
22
+ email: anderson.leite@caelum.com.br
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README.markdown
29
+ files:
30
+ - Gemfile
31
+ - init.rb
32
+ - install.rb
33
+ - MIT-LICENSE
34
+ - Rakefile
35
+ - README.markdown
36
+ - test.sqlite3
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
47
+ - test/dsl_test.rb
48
+ - test/filtered_relation_test.rb
49
+ - test/schema.rb
50
+ - test/test_helper.rb
51
+ has_rdoc: true
52
+ homepage: http://github.com/caelum/relata
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ segments:
66
+ - 0
67
+ version: "0"
68
+ required_rubygems_version: !ruby/object:Gem::Requirement
69
+ none: false
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ segments:
74
+ - 0
75
+ version: "0"
76
+ requirements: []
77
+
78
+ rubyforge_project:
79
+ rubygems_version: 1.3.7
80
+ signing_key:
81
+ specification_version: 3
82
+ summary: Helps poking around with relationships when using ARel
83
+ test_files: []
84
+