active_record_patch_first_or_create 1.0.0 → 1.1.0
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.
- checksums.yaml +4 -4
- data/README.md +6 -2
- data/active_record_patch_first_or_create.gemspec +5 -5
- data/lib/active_record_patch_first_or_create.rb +6 -9
- data/lib/active_record_patch_first_or_create/arel_query_creator.rb +42 -0
- data/lib/active_record_patch_first_or_create/version.rb +1 -1
- metadata +14 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b56bc4e68ceb6b1ae6089c20fe56b25d324497fa
|
4
|
+
data.tar.gz: 7d90a7e02899bee82c47cf3f260998b6cfb7ec11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 391e2fe0cf2643db27a2cd3e4bff5d470b396f9f5e529aae934f64d8055f87ce4417383aaeffcb6e525f51b4627fbdfcdd942a709cee8adf32af07a0d24966e7
|
7
|
+
data.tar.gz: de16600866569f8b6ee9f409ee49046fbfeab5a6641a0b0eddd50cf05e7264906bbdce2845002031cb2fb1129dd43e35f0792c7663912b3ee871a9fc8bbd7f86
|
data/README.md
CHANGED
@@ -26,15 +26,19 @@ We find out that methods like first_or_create or find_or_create_by are not atomi
|
|
26
26
|
|
27
27
|
Finds the first record with the given attributes, or creates a record with the attributes if one is not found:
|
28
28
|
|
29
|
+
```ruby
|
29
30
|
# Find the first user with uid "abc123" or create a new one.
|
30
31
|
User.where(uid: 'abc123').atomic_first_or_create(name: 'John', uid: 'abc123')
|
31
32
|
# => #<User id: 1, uid: "abc123", name: 'John'>
|
32
|
-
|
33
|
+
```
|
34
|
+
```ruby
|
33
35
|
# Find the first user with uid "abc123" or create a new one.
|
34
36
|
# We already have one so the existing record will be returned.
|
35
37
|
User.where(uid: 'abc123').atomic_first_or_create(name: 'John', uid: 'abc123')
|
36
38
|
# => #<User id: 1, uid: "abc123", name: 'John'>
|
37
|
-
|
39
|
+
```
|
40
|
+
```ruby
|
38
41
|
# Find the first user with uid "abc1234" or create a new one
|
39
42
|
User.where(uid: 'abc123').atomic_first_or_create(name: 'Johansson', uid: 'abc1234')
|
40
43
|
# => #<User id: 2, uid: "abc1234", name: 'Johansson'>
|
44
|
+
```
|
@@ -20,9 +20,9 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_development_dependency "bundler", "~> 1.5"
|
22
22
|
spec.add_development_dependency "rake", "~> 0"
|
23
|
-
spec.add_development_dependency "minitest"
|
24
|
-
spec.add_development_dependency "mocha"
|
25
|
-
spec.add_development_dependency "webmock"
|
26
|
-
spec.add_development_dependency "activerecord"
|
27
|
-
spec.add_development_dependency "sqlite3"
|
23
|
+
spec.add_development_dependency "minitest", "~> 0"
|
24
|
+
spec.add_development_dependency "mocha", "~> 0"
|
25
|
+
spec.add_development_dependency "webmock", "~> 0"
|
26
|
+
spec.add_development_dependency "activerecord", "~> 0"
|
27
|
+
spec.add_development_dependency "sqlite3", "~> 0"
|
28
28
|
end
|
@@ -1,16 +1,14 @@
|
|
1
1
|
require "active_record_patch_first_or_create/version"
|
2
|
+
require "active_record_patch_first_or_create/arel_query_creator"
|
2
3
|
|
3
4
|
module ActiveRecordPatchFirstOrCreate
|
4
5
|
def self.first_or_create relation, attributes
|
6
|
+
|
5
7
|
attributes = attributes.merge(relation.where_values_hash)
|
6
8
|
attributes = attributes.merge(rails_timestamps(relation))
|
7
9
|
attributes = serialize_columns(relation, attributes)
|
8
10
|
|
9
|
-
|
10
|
-
SELECT #{(['?'] * attributes.values.count).join(', ')}
|
11
|
-
WHERE NOT EXISTS (#{relation.select('1').to_sql})"
|
12
|
-
|
13
|
-
relation.klass.find_by_sql([sql] + attributes.values)
|
11
|
+
ActiveRecord::Base.connection.execute(ArelQueryCreator.new(relation, attributes).to_sql)
|
14
12
|
|
15
13
|
relation.first
|
16
14
|
end
|
@@ -22,9 +20,8 @@ module ActiveRecordPatchFirstOrCreate
|
|
22
20
|
|
23
21
|
def self.serialize_columns relation, attributes
|
24
22
|
Hash[attributes.map do |key, value|
|
25
|
-
|
26
|
-
|
27
|
-
[key, value]
|
23
|
+
column = relation.klass.columns.find { |c| c.name == key.to_s }
|
24
|
+
[key, column ? column.cast_type.type_cast_for_database(value) : value]
|
28
25
|
end]
|
29
26
|
end
|
30
27
|
end
|
@@ -35,4 +32,4 @@ module ActiveRecord
|
|
35
32
|
ActiveRecordPatchFirstOrCreate.first_or_create(self, attributes)
|
36
33
|
end
|
37
34
|
end
|
38
|
-
end
|
35
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ActiveRecordPatchFirstOrCreate
|
2
|
+
class ArelQueryCreator < Struct.new(:relation, :attributes)
|
3
|
+
def to_sql
|
4
|
+
insert_query.to_sql
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def insert_query
|
10
|
+
manager = Arel::InsertManager.new(ActiveRecord::Base)
|
11
|
+
manager.into table
|
12
|
+
|
13
|
+
attributes.keys.each do |name|
|
14
|
+
manager.columns << table[name]
|
15
|
+
end
|
16
|
+
|
17
|
+
manager.select select_query
|
18
|
+
manager
|
19
|
+
end
|
20
|
+
|
21
|
+
def select_query
|
22
|
+
select = Arel::SelectManager.new(ActiveRecord::Base)
|
23
|
+
attributes.values.each do |value|
|
24
|
+
select.project Arel.sql(ActiveRecord::Base.connection.quote(value))
|
25
|
+
end
|
26
|
+
select.where(not_exists_query.exists.not)
|
27
|
+
select
|
28
|
+
end
|
29
|
+
|
30
|
+
def not_exists_query
|
31
|
+
query = table.project(Arel.sql('1'))
|
32
|
+
relation.where_values_hash.each do |k,v|
|
33
|
+
query.where(table[k.to_sym].eq(v))
|
34
|
+
end
|
35
|
+
query
|
36
|
+
end
|
37
|
+
|
38
|
+
def table
|
39
|
+
Arel::Table.new relation.table_name
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_record_patch_first_or_create
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- NDrive DevOps Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -42,70 +42,70 @@ dependencies:
|
|
42
42
|
name: minitest
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '0'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: mocha
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
type: :development
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: webmock
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
type: :development
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
84
|
name: activerecord
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
type: :development
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - "~>"
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: '0'
|
97
97
|
- !ruby/object:Gem::Dependency
|
98
98
|
name: sqlite3
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
100
100
|
requirements:
|
101
|
-
- - "
|
101
|
+
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
|
-
- - "
|
108
|
+
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
110
|
version: '0'
|
111
111
|
description: This patch provides first_or_create method to be atomic, once the default
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- Rakefile
|
123
123
|
- active_record_patch_first_or_create.gemspec
|
124
124
|
- lib/active_record_patch_first_or_create.rb
|
125
|
+
- lib/active_record_patch_first_or_create/arel_query_creator.rb
|
125
126
|
- lib/active_record_patch_first_or_create/version.rb
|
126
127
|
homepage: http://www.ndrive.com
|
127
128
|
licenses:
|
@@ -143,7 +144,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
143
144
|
version: '0'
|
144
145
|
requirements: []
|
145
146
|
rubyforge_project:
|
146
|
-
rubygems_version: 2.
|
147
|
+
rubygems_version: 2.4.3
|
147
148
|
signing_key:
|
148
149
|
specification_version: 4
|
149
150
|
summary: ActiveRecord patch first_or_create atomic version
|