in_place_relation 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/.hgignore ADDED
@@ -0,0 +1,2 @@
1
+ syntax: glob
2
+ *swp
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
@@ -1 +1,9 @@
1
1
  require "bundler/gem_tasks"
2
+
3
+ # Now I have no idea why this doesn't work without specifying the task explicitly
4
+ require "rake/testtask"
5
+ Rake::TestTask.new do |t|
6
+ t.libs << "test"
7
+ t.test_files = FileList['test/*test.rb']
8
+ t.verbose = true
9
+ end
@@ -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
- # specify any dependencies here; for example:
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
@@ -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
- return Wrapper.new( self )
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
@@ -1,3 +1,3 @@
1
1
  module InPlaceRelation
2
- VERSION = "0.1.0"
2
+ VERSION = "0.1.1"
3
3
  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: 27
4
+ hash: 25
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 0
10
- version: 0.1.0
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: 2011-11-28 00:00:00 +01:00
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: *id001
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