in_place_relation 0.1.0 → 0.1.1
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/.hgignore +2 -0
- data/README +19 -0
- data/Rakefile +8 -0
- data/in_place_relation.gemspec +1 -2
- data/lib/in_place_relation.rb +10 -14
- data/lib/in_place_relation/version.rb +1 -1
- data/test/in_place_relation_test.rb +118 -0
- metadata +25 -8
data/.hgignore
ADDED
data/README
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# This module provides an in-place wrapper for ActiveRecord::Relation.
|
2
|
+
#
|
3
|
+
# So instead of doing this:
|
4
|
+
# rel = SomeModel.where( ... )
|
5
|
+
# rel = rel.joins(...).where(...) if x
|
6
|
+
# rel = rel.select(...) unless y
|
7
|
+
# rel = rel.merge( another_rel )
|
8
|
+
# rel.all
|
9
|
+
#
|
10
|
+
# you can do this:
|
11
|
+
# rel = SomeModel.where( ... ).in_place
|
12
|
+
# rel.joins(...).where(...) if x
|
13
|
+
# rel.select(...) unless y
|
14
|
+
# rel.merge( another_rel )
|
15
|
+
# rel.all
|
16
|
+
#
|
17
|
+
# All ActiveRecord::Relation methods are either wrapped and return wrapper
|
18
|
+
# itself or are passed directly to underlying relation object. In rare case you
|
19
|
+
# might want to access this relation object directly, use #relation method
|
data/Rakefile
CHANGED
data/in_place_relation.gemspec
CHANGED
@@ -18,7 +18,6 @@ Gem::Specification.new do |s|
|
|
18
18
|
s.executables = `hg manifest | grep ^bin`.split("\n").map{ |f| File.basename(f) }
|
19
19
|
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
|
22
|
-
# s.add_development_dependency "rspec"
|
21
|
+
s.add_development_dependency "activerecord-nulldb-adapter"
|
23
22
|
s.add_runtime_dependency "activerecord", ">= 3"
|
24
23
|
end
|
data/lib/in_place_relation.rb
CHANGED
@@ -1,17 +1,5 @@
|
|
1
1
|
require "in_place_relation/version"
|
2
2
|
|
3
|
-
# This module provides an in-place wrapper for ActiveRecord::Relation. So
|
4
|
-
# instead of doing this:
|
5
|
-
# rel = SomeModel.where( ... )
|
6
|
-
# rel = rel.joins().where() if x
|
7
|
-
# rel = rel.select() unless y
|
8
|
-
# rel.all
|
9
|
-
#
|
10
|
-
# you can do this
|
11
|
-
# rel = SomeModel.where( ... ).in_place
|
12
|
-
# rel.joins().where() if x
|
13
|
-
# rel.select() unless y
|
14
|
-
# rel.all
|
15
3
|
#
|
16
4
|
# and get original relation with:
|
17
5
|
# rel.relation # ActiveRecord::Relation
|
@@ -20,17 +8,21 @@ module InPlaceRelation
|
|
20
8
|
module Methods
|
21
9
|
|
22
10
|
def in_place
|
23
|
-
|
11
|
+
# To keep things unified we always want a Relation here even if initial
|
12
|
+
# object was a model class or an association
|
13
|
+
rel = self.is_a?( ActiveRecord::Relation ) ? self : self.scoped
|
14
|
+
return Wrapper.new( rel )
|
24
15
|
end
|
25
16
|
end
|
26
17
|
|
27
18
|
class Wrapper
|
28
19
|
|
20
|
+
# Wrapped ActiveRecord::Relation object
|
29
21
|
attr_reader :relation
|
30
22
|
|
31
23
|
METHODS_TO_WRAP = ActiveRecord::Relation::ASSOCIATION_METHODS + ActiveRecord::Relation::MULTI_VALUE_METHODS + ActiveRecord::Relation::SINGLE_VALUE_METHODS + [:merge]
|
32
24
|
|
33
|
-
METHODS_TO_WRAP.each do |meth|
|
25
|
+
METHODS_TO_WRAP.uniq.each do |meth|
|
34
26
|
define_method( meth ) do |*args|
|
35
27
|
@relation = @relation.send( meth, *args )
|
36
28
|
return self
|
@@ -49,6 +41,10 @@ module InPlaceRelation
|
|
49
41
|
@relation.send( name, *args, &block )
|
50
42
|
end
|
51
43
|
|
44
|
+
def in_place
|
45
|
+
return self
|
46
|
+
end
|
47
|
+
|
52
48
|
end
|
53
49
|
|
54
50
|
end
|
@@ -0,0 +1,118 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'in_place_relation'
|
4
|
+
|
5
|
+
# Workaround for nulldb Rails 3.1 incompatibility
|
6
|
+
class Object
|
7
|
+
|
8
|
+
def returning( obj, &block )
|
9
|
+
obj.tap( &block )
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class InPlaceRelationTest < Test::Unit::TestCase
|
14
|
+
|
15
|
+
ActiveRecord::Base.establish_connection :adapter => :nulldb
|
16
|
+
|
17
|
+
class Post < ActiveRecord::Base
|
18
|
+
has_many :comments
|
19
|
+
end
|
20
|
+
|
21
|
+
class Comment < ActiveRecord::Base
|
22
|
+
belongs_to :post
|
23
|
+
end
|
24
|
+
|
25
|
+
Post.connection.create_table "posts" do |t|
|
26
|
+
t.string :name
|
27
|
+
t.text :content
|
28
|
+
t.timestamps
|
29
|
+
end
|
30
|
+
|
31
|
+
Comment.connection.create_table "comments" do |t|
|
32
|
+
t.integer :post_id
|
33
|
+
t.string :title
|
34
|
+
t.text :content
|
35
|
+
t.timestamps
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_on_class
|
39
|
+
rel = Post.in_place
|
40
|
+
oid = rel.object_id
|
41
|
+
rel.where( :id => 1 )
|
42
|
+
rel.joins( :comments )
|
43
|
+
rel.order( "id DESC" )
|
44
|
+
rel.limit( 20 )
|
45
|
+
rel.select( "DISTINCT posts.id" )
|
46
|
+
assert_equal oid, rel.object_id
|
47
|
+
assert_equal "posts.id = 1", rel.where_values.first.to_sql
|
48
|
+
#assert_equal "INNER JOIN comments ON comments.post_id = posts.id", rel.joins_values.first.to_sql
|
49
|
+
assert_equal "id DESC", rel.order_values.first
|
50
|
+
assert_equal 20, rel.limit_value
|
51
|
+
assert_equal "DISTINCT posts.id", rel.select_values.first
|
52
|
+
end
|
53
|
+
|
54
|
+
# This test doesn't work without database connection, probably passing schema
|
55
|
+
# to nulldb would suffice
|
56
|
+
def test_on_association
|
57
|
+
p = Post.create!( :id => 11 )
|
58
|
+
rel = p.comments.in_place
|
59
|
+
oid = rel.object_id
|
60
|
+
rel.where( :name => "NAME" )
|
61
|
+
rel.joins( :comments )
|
62
|
+
rel.order( "id DESC" )
|
63
|
+
rel.limit( 20 )
|
64
|
+
rel.select( "DISTINCT posts.id" )
|
65
|
+
assert_equal oid, rel.object_id
|
66
|
+
assert_equal "posts.id = 1", rel.where_sql
|
67
|
+
#assert_equal "INNER JOIN comments ON comments.post_id = posts.id", rel.joins_values.first.to_sql
|
68
|
+
assert_equal "id DESC", rel.order_values.first
|
69
|
+
assert_equal 20, rel.limit_value
|
70
|
+
assert_equal "DISTINCT posts.id", rel.select_values.first
|
71
|
+
end
|
72
|
+
|
73
|
+
def test_on_relation
|
74
|
+
rel = Post.where( :name => "some" ).in_place
|
75
|
+
oid = rel.object_id
|
76
|
+
rel.where( :id => 1 )
|
77
|
+
rel.joins( :comments )
|
78
|
+
rel.order( "id DESC" )
|
79
|
+
rel.limit( 20 )
|
80
|
+
rel.select( "DISTINCT posts.id" )
|
81
|
+
assert_equal oid, rel.object_id
|
82
|
+
assert_equal "WHERE posts.name = 'some' AND posts.id = 1", rel.where_sql
|
83
|
+
#assert_equal "INNER JOIN comments ON comments.post_id = posts.id", rel.joins_values.first.to_sql
|
84
|
+
assert_equal "id DESC", rel.order_values.first
|
85
|
+
assert_equal 20, rel.limit_value
|
86
|
+
assert_equal "DISTINCT posts.id", rel.select_values.first
|
87
|
+
end
|
88
|
+
|
89
|
+
def test_in_place_identity
|
90
|
+
rel = Comment.in_place
|
91
|
+
oid = rel.object_id
|
92
|
+
10.times { rel = rel.in_place }
|
93
|
+
assert_equal oid, rel.object_id
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_where_chaining
|
97
|
+
rel = Post.where( :id => 1 ).in_place
|
98
|
+
rel.where( :id => 2, :name => "adsf" ).where( :created_at => "2011-01-01 00:00:00" ).where( "content LIKE ?", "%content word%" )
|
99
|
+
assert_equal "WHERE posts.id = 1 AND posts.id = 2 AND posts.name = 'adsf' AND posts.created_at = '2011-01-01 00:00:00' AND (content LIKE '%content word%')", rel.where_sql
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_relation_identity
|
103
|
+
rel = Comment.where( :title => 'fdsa' )
|
104
|
+
wrap = rel.in_place
|
105
|
+
assert_equal rel.object_id, wrap.relation.object_id
|
106
|
+
assert_equal rel.where_sql, wrap.relation.where_sql
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_merge
|
110
|
+
rel = Comment.where( :title => 'fdsa' )
|
111
|
+
wrap = Comment.where( :post_id => 43 ).in_place
|
112
|
+
oid = wrap.object_id
|
113
|
+
wrap.merge( rel )
|
114
|
+
assert_equal oid, wrap.object_id
|
115
|
+
assert_equal "WHERE comments.post_id = 43 AND comments.title = 'fdsa'", wrap.where_sql
|
116
|
+
end
|
117
|
+
|
118
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: in_place_relation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Marek Janukowicz/Starware
|
@@ -15,13 +15,27 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date:
|
18
|
+
date: 2012-01-03 00:00:00 +01:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
name: activerecord
|
22
|
+
name: activerecord-nulldb-adapter
|
23
23
|
prerelease: false
|
24
24
|
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :development
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: activerecord
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
25
39
|
none: false
|
26
40
|
requirements:
|
27
41
|
- - ">="
|
@@ -31,7 +45,7 @@ dependencies:
|
|
31
45
|
- 3
|
32
46
|
version: "3"
|
33
47
|
type: :runtime
|
34
|
-
version_requirements: *
|
48
|
+
version_requirements: *id002
|
35
49
|
description: ActiveRecord::Relation wrapper that can be modified/combined in place
|
36
50
|
email:
|
37
51
|
- marek@janukowicz.net
|
@@ -42,11 +56,14 @@ extensions: []
|
|
42
56
|
extra_rdoc_files: []
|
43
57
|
|
44
58
|
files:
|
59
|
+
- .hgignore
|
45
60
|
- Gemfile
|
61
|
+
- README
|
46
62
|
- Rakefile
|
47
63
|
- in_place_relation.gemspec
|
48
64
|
- lib/in_place_relation.rb
|
49
65
|
- lib/in_place_relation/version.rb
|
66
|
+
- test/in_place_relation_test.rb
|
50
67
|
has_rdoc: true
|
51
68
|
homepage: ""
|
52
69
|
licenses: []
|
@@ -81,5 +98,5 @@ rubygems_version: 1.6.2
|
|
81
98
|
signing_key:
|
82
99
|
specification_version: 3
|
83
100
|
summary: A relation that can be changed in place
|
84
|
-
test_files:
|
85
|
-
|
101
|
+
test_files:
|
102
|
+
- test/in_place_relation_test.rb
|