returning 0.0.3 → 0.0.4
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/.travis.yml +0 -1
- data/CHANGELOG.md +3 -0
- data/lib/returning.rb +20 -7
- data/lib/returning/active_record/returning.rb +26 -19
- data/lib/returning/arel/delete_update_manager.rb +10 -0
- data/lib/returning/arel/nodes/delete_update_statement.rb +14 -0
- data/lib/returning/arel/nodes/returning.rb +18 -0
- data/lib/returning/arel/nodes/select_core.rb +14 -0
- data/lib/returning/arel/tree_manager.rb +10 -0
- data/lib/returning/arel/visitors/postgresql.rb +32 -0
- data/lib/returning/rails30/active_record/persistence.rb +29 -0
- data/lib/returning/rails30/arel/crud.rb +42 -0
- data/lib/returning/rails30/returning.rb +6 -0
- data/lib/returning/rails31/active_record/persistence.rb +51 -0
- data/lib/returning/rails31/arel/crud.rb +32 -0
- data/lib/returning/rails31/returning.rb +6 -0
- data/lib/returning/version.rb +1 -1
- data/spec/returning_spec.rb +12 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/support/ar.rb +12 -0
- metadata +16 -4
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
0.0.4 - 2011-08-24
|
2
|
+
* Save returning in an instance variable of the model, instead of connection. Previous approach failed when you tried to load an association inside a callback.
|
3
|
+
|
1
4
|
0.0.3 - 2011-08-22
|
2
5
|
-----
|
3
6
|
* Pass parameters down on save. This makes update_attribute work.
|
data/lib/returning.rb
CHANGED
@@ -2,14 +2,27 @@ require 'active_record'
|
|
2
2
|
require 'active_record/connection_adapters/postgresql_adapter'
|
3
3
|
|
4
4
|
require "returning/version"
|
5
|
-
|
6
|
-
require 'returning/
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
#
|
5
|
+
if ActiveRecord::VERSION::STRING =~ /^3\.0/
|
6
|
+
require 'returning/rails30/returning'
|
7
|
+
elsif ActiveRecord::VERSION::STRING =~ /^3\.1/
|
8
|
+
require 'returning/rails31/returning'
|
9
|
+
else
|
10
|
+
raise "ActiveRecord version #{ActiveRecord::VERSION::STRING} is not supported!"
|
11
11
|
end
|
12
12
|
|
13
|
+
require 'returning/active_record/returning'
|
14
|
+
require 'returning/arel/tree_manager'
|
15
|
+
require 'returning/arel/nodes/select_core'
|
16
|
+
require 'returning/arel/nodes/returning'
|
17
|
+
require 'returning/arel/delete_update_manager'
|
18
|
+
require 'returning/arel/nodes/delete_update_statement'
|
19
|
+
require 'returning/arel/visitors/postgresql'
|
13
20
|
|
14
21
|
ActiveRecord::Base.send(:include, Returning::ActiveRecord::Returning)
|
15
|
-
|
22
|
+
Arel::SelectManager.send(:include, Returning::Arel::TreeManager)
|
23
|
+
Arel::UpdateManager.send(:include, Returning::Arel::DeleteUpdateManager)
|
24
|
+
Arel::DeleteManager.send(:include, Returning::Arel::DeleteUpdateManager)
|
25
|
+
Arel::Nodes::SelectCore.send(:include, Returning::Arel::Nodes::SelectCore)
|
26
|
+
Arel::Nodes::UpdateStatement.send(:include, Returning::Arel::Nodes::DeleteUpdateStatement)
|
27
|
+
Arel::Nodes::DeleteStatement.send(:include, Returning::Arel::Nodes::DeleteUpdateStatement)
|
28
|
+
Arel::Visitors::PostgreSQL.send(:include, Returning::Arel::Visitors::PostgreSQL)
|
@@ -3,22 +3,13 @@ require 'active_support/concern'
|
|
3
3
|
module Returning
|
4
4
|
module ActiveRecord
|
5
5
|
module Returning
|
6
|
-
extend ActiveSupport::Concern
|
7
|
-
|
8
|
-
included do
|
9
|
-
if method(:find_by_sql).arity == 1
|
10
|
-
class_eval do
|
11
|
-
def self.find_by_sql(sql, binds = [])
|
12
|
-
connection.select_all(sanitize_sql(sql), "#{name} Load").collect! { |record| instantiate(record) }
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
6
|
def save(options = {})
|
19
7
|
if r = options[:returning]
|
20
|
-
|
8
|
+
begin
|
9
|
+
old_returning, @_returning = @_returning, r
|
21
10
|
super
|
11
|
+
ensure
|
12
|
+
@_returning = old_returning
|
22
13
|
end
|
23
14
|
else
|
24
15
|
super
|
@@ -26,10 +17,18 @@ module Returning
|
|
26
17
|
end
|
27
18
|
|
28
19
|
def create_or_update
|
29
|
-
if
|
30
|
-
|
31
|
-
|
32
|
-
|
20
|
+
if @_returning
|
21
|
+
raise ReadOnlyRecord if readonly?
|
22
|
+
if new_record?
|
23
|
+
create
|
24
|
+
self
|
25
|
+
elsif r = update
|
26
|
+
r = self.class.send(:instantiate, r[0])
|
27
|
+
r.readonly!
|
28
|
+
r
|
29
|
+
else
|
30
|
+
false
|
31
|
+
end
|
33
32
|
else
|
34
33
|
super
|
35
34
|
end
|
@@ -37,8 +36,16 @@ module Returning
|
|
37
36
|
|
38
37
|
def destroy(options = {})
|
39
38
|
if r = options[:returning]
|
40
|
-
|
41
|
-
|
39
|
+
begin
|
40
|
+
old_returning, @_returning = @_returning, r
|
41
|
+
if r = super()
|
42
|
+
r = self.class.send(:instantiate, r[0])
|
43
|
+
r.readonly!
|
44
|
+
end
|
45
|
+
|
46
|
+
r
|
47
|
+
ensure
|
48
|
+
@_returning = old_returning
|
42
49
|
end
|
43
50
|
else
|
44
51
|
super()
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Returning
|
2
|
+
module Arel
|
3
|
+
module Nodes
|
4
|
+
class Returning < ::Arel::Nodes::Node
|
5
|
+
attr_accessor :returnings
|
6
|
+
|
7
|
+
def initialize(returnings)
|
8
|
+
@returnings = returnings
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize_copy other
|
12
|
+
super
|
13
|
+
@returnings = @returnings.clone if @returnings
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Returning
|
2
|
+
module Arel
|
3
|
+
module Visitors
|
4
|
+
module PostgreSQL
|
5
|
+
private
|
6
|
+
def visit_Returning_Arel_Nodes_Returning o
|
7
|
+
if o.returnings.empty?
|
8
|
+
""
|
9
|
+
else
|
10
|
+
" RETURNING #{o.returnings.join(', ')}"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def visit_Arel_Nodes_UpdateStatement o
|
15
|
+
if o.returnings
|
16
|
+
"#{super}#{visit o.returnings}"
|
17
|
+
else
|
18
|
+
super
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def visit_Arel_Nodes_DeleteStatement o
|
23
|
+
if o.returnings
|
24
|
+
"#{super}#{visit o.returnings}"
|
25
|
+
else
|
26
|
+
super
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Returning
|
2
|
+
module Rails30
|
3
|
+
module ActiveRecord
|
4
|
+
module Persistence
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
included do
|
7
|
+
def update(attribute_names = @attributes.keys, options = {})
|
8
|
+
attributes_with_values = arel_attributes_values(false, false, attribute_names)
|
9
|
+
return @_returning ? [@attributes] : 0 if attributes_with_values.empty?
|
10
|
+
self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).arel.returning(@_returning).update(attributes_with_values)
|
11
|
+
end
|
12
|
+
|
13
|
+
def destroy
|
14
|
+
destroy_associations
|
15
|
+
|
16
|
+
if persisted?
|
17
|
+
result = self.class.unscoped.where(self.class.arel_table[self.class.primary_key].eq(id)).arel.returning(@_returning).delete
|
18
|
+
end
|
19
|
+
|
20
|
+
@destroyed = true
|
21
|
+
freeze
|
22
|
+
|
23
|
+
result ? result : self
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module Returning
|
2
|
+
module Rails30
|
3
|
+
module Arel
|
4
|
+
module Crud
|
5
|
+
def update values
|
6
|
+
um = ::Arel::UpdateManager.new @engine
|
7
|
+
|
8
|
+
if ::Arel::Nodes::SqlLiteral === values
|
9
|
+
relation = @ctx.froms
|
10
|
+
else
|
11
|
+
relation = values.first.first.relation
|
12
|
+
end
|
13
|
+
um.table relation
|
14
|
+
um.set values
|
15
|
+
um.take @ast.limit.expr if @ast.limit
|
16
|
+
um.order(*@ast.orders)
|
17
|
+
um.wheres = @ctx.wheres
|
18
|
+
um.returning @ctx.returnings if @ctx.returnings
|
19
|
+
|
20
|
+
if @ctx.returnings
|
21
|
+
@engine.connection.select_all um.to_sql, 'AREL'
|
22
|
+
else
|
23
|
+
@engine.connection.update um.to_sql, 'AREL'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def delete
|
28
|
+
dm = ::Arel::DeleteManager.new @engine
|
29
|
+
dm.wheres = @ctx.wheres
|
30
|
+
dm.from @ctx.froms
|
31
|
+
dm.returning @ctx.returnings if @ctx.returnings
|
32
|
+
|
33
|
+
if @ctx.returnings
|
34
|
+
@engine.connection.select_all dm.to_sql, 'AREL'
|
35
|
+
else
|
36
|
+
@engine.connection.delete dm.to_sql, 'AREL'
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module Returning
|
2
|
+
module Rails31
|
3
|
+
module ActiveRecord
|
4
|
+
module Persistence
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
included do
|
7
|
+
def update(attribute_names = @attributes.keys)
|
8
|
+
attributes_with_values = arel_attributes_values(false, false, attribute_names)
|
9
|
+
return @_returning ? [@attributes] : 0 if attributes_with_values.empty?
|
10
|
+
klass = self.class
|
11
|
+
stmt = klass.unscoped.where(klass.arel_table[klass.primary_key].eq(id)).arel.returning(@_returning).compile_update(attributes_with_values)
|
12
|
+
if @_returning
|
13
|
+
klass.connection.select_all stmt
|
14
|
+
else
|
15
|
+
klass.connection.update stmt
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def destroy
|
20
|
+
destroy_associations
|
21
|
+
|
22
|
+
if persisted?
|
23
|
+
::ActiveRecord::IdentityMap.remove(self) if ::ActiveRecord::IdentityMap.enabled?
|
24
|
+
pk = self.class.primary_key
|
25
|
+
column = self.class.columns_hash[pk]
|
26
|
+
substitute = connection.substitute_at(column, 0)
|
27
|
+
|
28
|
+
relation = self.class.unscoped.where(
|
29
|
+
self.class.arel_table[pk].eq(substitute))
|
30
|
+
|
31
|
+
relation.bind_values = [[column, id]]
|
32
|
+
stmt = relation.arel.returning(@_returning).compile_delete
|
33
|
+
|
34
|
+
klass = self.class
|
35
|
+
result = if @_returning
|
36
|
+
klass.connection.select_all stmt, 'SQL', relation.bind_values
|
37
|
+
else
|
38
|
+
klass.connection.delete stmt, 'SQL', relation.bind_values
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
@destroyed = true
|
43
|
+
freeze
|
44
|
+
|
45
|
+
result ? result : self
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Returning
|
2
|
+
module Rails31
|
3
|
+
module Arel
|
4
|
+
module Crud
|
5
|
+
def compile_update values
|
6
|
+
um = ::Arel::UpdateManager.new @engine
|
7
|
+
|
8
|
+
if ::Arel::Nodes::SqlLiteral === values
|
9
|
+
relation = @ctx.from
|
10
|
+
else
|
11
|
+
relation = values.first.first.relation
|
12
|
+
end
|
13
|
+
um.table relation
|
14
|
+
um.set values
|
15
|
+
um.take @ast.limit.expr if @ast.limit
|
16
|
+
um.order(*@ast.orders)
|
17
|
+
um.wheres = @ctx.wheres
|
18
|
+
um.returning @ctx.returnings if @ctx.returnings
|
19
|
+
um
|
20
|
+
end
|
21
|
+
|
22
|
+
def compile_delete
|
23
|
+
dm = ::Arel::DeleteManager.new @engine
|
24
|
+
dm.wheres = @ctx.wheres
|
25
|
+
dm.from @ctx.froms
|
26
|
+
dm.returning @ctx.returnings if @ctx.returnings
|
27
|
+
dm
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/returning/version.rb
CHANGED
data/spec/returning_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'spec_helper'
|
2
|
+
require 'logger'
|
2
3
|
|
3
4
|
describe Returning do
|
4
5
|
before do
|
@@ -37,13 +38,23 @@ describe Returning do
|
|
37
38
|
post.save(:returning => "name", :validate => false).should be_true
|
38
39
|
end
|
39
40
|
end
|
41
|
+
|
42
|
+
context 'works fine with associations' do
|
43
|
+
it "does not pollute destroy with RETURNING of an association" do
|
44
|
+
post = Post.first
|
45
|
+
post.update_attributes :tags_attributes => [{:tag => 'a'}, {:tag => 'b'}]
|
46
|
+
post.tags_attributes = Post.find(post.id).tags.map { |t| {:id => t.id, :_destroy => '1'} }
|
47
|
+
post.name = 'New name'
|
48
|
+
post.save(:returning => 'name')
|
49
|
+
end
|
50
|
+
end
|
40
51
|
end
|
41
52
|
|
42
53
|
describe '#destroy' do
|
43
54
|
it 'returns the column passed to returning' do
|
44
55
|
post = Post.first
|
45
56
|
post.name = 'hello world'
|
46
|
-
post.destroy(:returning => 'name').name.should == 'hello
|
57
|
+
post.destroy(:returning => 'name').name.should == 'hello'
|
47
58
|
end
|
48
59
|
|
49
60
|
context 'with query cache' do
|
data/spec/spec_helper.rb
CHANGED
data/spec/support/ar.rb
CHANGED
@@ -23,16 +23,28 @@ class Migration < ActiveRecord::Migration
|
|
23
23
|
create_table :posts, :force => true do |t|
|
24
24
|
t.string :name, :author
|
25
25
|
end
|
26
|
+
create_table :tags, :force => true do |t|
|
27
|
+
t.string :tag
|
28
|
+
t.references :post
|
29
|
+
end
|
26
30
|
end
|
27
31
|
|
28
32
|
def self.down
|
29
33
|
drop_table :posts
|
34
|
+
drop_table :tags
|
30
35
|
end
|
31
36
|
end
|
32
37
|
|
33
38
|
Migration.up
|
34
39
|
|
35
40
|
class Post < ActiveRecord::Base
|
41
|
+
has_many :tags
|
42
|
+
|
43
|
+
accepts_nested_attributes_for :tags, :allow_destroy => true
|
44
|
+
end
|
45
|
+
|
46
|
+
class Tag < ActiveRecord::Base
|
47
|
+
belongs_to :post
|
36
48
|
end
|
37
49
|
|
38
50
|
class PostQueryCache < ActiveRecord::Base
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: returning
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 4
|
10
|
+
version: 0.0.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Eugene Pimenov
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-08-
|
18
|
+
date: 2011-08-24 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
requirement: &id001 !ruby/object:Gem::Requirement
|
@@ -67,6 +67,18 @@ files:
|
|
67
67
|
- lib/returning.rb
|
68
68
|
- lib/returning/active_record/adapter.rb
|
69
69
|
- lib/returning/active_record/returning.rb
|
70
|
+
- lib/returning/arel/delete_update_manager.rb
|
71
|
+
- lib/returning/arel/nodes/delete_update_statement.rb
|
72
|
+
- lib/returning/arel/nodes/returning.rb
|
73
|
+
- lib/returning/arel/nodes/select_core.rb
|
74
|
+
- lib/returning/arel/tree_manager.rb
|
75
|
+
- lib/returning/arel/visitors/postgresql.rb
|
76
|
+
- lib/returning/rails30/active_record/persistence.rb
|
77
|
+
- lib/returning/rails30/arel/crud.rb
|
78
|
+
- lib/returning/rails30/returning.rb
|
79
|
+
- lib/returning/rails31/active_record/persistence.rb
|
80
|
+
- lib/returning/rails31/arel/crud.rb
|
81
|
+
- lib/returning/rails31/returning.rb
|
70
82
|
- lib/returning/version.rb
|
71
83
|
- returning.gemspec
|
72
84
|
- spec/returning_spec.rb
|