atomically 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +12 -4
- data/atomically.gemspec +2 -1
- data/lib/atomically/active_record/extension.rb +1 -1
- data/lib/atomically/patches/from.rb +8 -0
- data/lib/atomically/patches/none.rb +7 -0
- data/lib/atomically/query_service.rb +37 -6
- data/lib/atomically/version.rb +1 -1
- metadata +22 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: d38cf83ab4f1e792cfefbb2c01ac897377fb7af2a81da6f09f932df4d5fa76f2
|
4
|
+
data.tar.gz: 88640837b4c69ef162d036b2a3e6ad61087e94a6baa79cde026fb748f09b58f1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cd968dcc060705bc3d0174daf532fa4c80b8dfadc5845a7406bcf68d930744c6ce78e2f04b97091eb4cea27818ed44df1e4b3c47eefac5e0643ab492b9bed21b
|
7
|
+
data.tar.gz: 7577dd5ef6f32a4d3753c71637d218358d48aeac8b7c675c9b780d906af56f08bd9cf5cb14d7b98fd12a9275d28f6d45ec8a5baaccb3b177257e300a04c0c890
|
data/README.md
CHANGED
@@ -31,20 +31,28 @@ Or install it yourself as:
|
|
31
31
|
### create_or_plus
|
32
32
|
|
33
33
|
Import an array of records. When key is duplicate, plus the old value with new value.
|
34
|
-
It is useful to add `items` to user when `user_items` may not exist.
|
34
|
+
It is useful to add `items` to `user` when `user_items` may not exist.
|
35
35
|
|
36
36
|
First two args (columns, values) are the same with the [import](https://github.com/zdennis/activerecord-import#columns-and-arrays) method.
|
37
37
|
|
38
38
|
Example:
|
39
|
-
|
40
39
|
```rb
|
41
|
-
columns = [:user_id, :item_id, :
|
40
|
+
columns = [:user_id, :item_id, :quantity]
|
42
41
|
values = [[user.id, item1.id, 3], [user.id, item2.id, 2]]
|
43
|
-
on_duplicate_update_columns = [:
|
42
|
+
on_duplicate_update_columns = [:quantity]
|
44
43
|
|
45
44
|
UserItem.atomically.create_or_plus(columns, values, on_duplicate_update_columns)
|
46
45
|
```
|
47
46
|
|
47
|
+
### pay_all
|
48
|
+
Reduce the quantity of items and return how many rows and updated if all of them is enough.
|
49
|
+
Do nothing and return zero if any of them is not enough.
|
50
|
+
|
51
|
+
Example:
|
52
|
+
```rb
|
53
|
+
user.user_items.atomically.pay_all({ item1.id => 4, item2.id => 3 }, [:quantity], primary_key: :item_id)
|
54
|
+
```
|
55
|
+
|
48
56
|
## Development
|
49
57
|
|
50
58
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test DB=mysql` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
data/atomically.gemspec
CHANGED
@@ -34,6 +34,7 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_development_dependency "mysql2", ">= 0.3"
|
35
35
|
spec.add_development_dependency "pluck_all", ">= 2.0.3"
|
36
36
|
|
37
|
-
spec.add_dependency "activerecord-import", ">= 0.27.0"
|
38
37
|
spec.add_dependency "activerecord", ">= 3"
|
38
|
+
spec.add_dependency "activerecord-import", ">= 0.27.0"
|
39
|
+
spec.add_dependency "rails_or", ">= 1.1.8"
|
39
40
|
end
|
@@ -1,21 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'activerecord-import'
|
4
|
+
require 'rails_or'
|
5
|
+
require 'atomically/patches/none' if not ActiveRecord::Base.respond_to?(:none)
|
6
|
+
require 'atomically/patches/from' if Gem::Version.new(ActiveRecord::VERSION::STRING) < Gem::Version.new('4.0.0')
|
2
7
|
|
3
8
|
class Atomically::QueryService
|
4
|
-
def initialize(klass)
|
9
|
+
def initialize(klass, relation: nil)
|
5
10
|
@klass = klass
|
11
|
+
@relation = relation || @klass
|
6
12
|
end
|
7
13
|
|
8
14
|
def create_or_plus(columns, data, update_columns)
|
9
15
|
@klass.import(columns, data, on_duplicate_key_update: on_duplicate_key_plus_sql(update_columns))
|
10
16
|
end
|
11
17
|
|
18
|
+
def pay_all(hash, update_columns, primary_key: :id) # { id => pay_count }
|
19
|
+
return 0 if hash.blank?
|
20
|
+
|
21
|
+
update_columns = update_columns.map(&method(:quote_column))
|
22
|
+
|
23
|
+
query = hash.inject(@klass.none) do |relation, (id, pay_count)|
|
24
|
+
condition = @relation.where(primary_key => id)
|
25
|
+
update_columns.each{|s| condition = condition.where("#{s} >= ?", pay_count) }
|
26
|
+
next relation.or(condition)
|
27
|
+
end
|
28
|
+
|
29
|
+
raw_when_sql = hash.map{|id, pay_count| "WHEN #{sanitize(id)} THEN #{sanitize(-pay_count)}" }.join("\n")
|
30
|
+
update_sqls = update_columns.map.with_index do |column, idx|
|
31
|
+
value = idx == 0 ? "(@change := \nCASE #{quote_column(primary_key)}\n#{raw_when_sql}\nEND)" : '@change'
|
32
|
+
next "#{column} = #{column} + #{value}"
|
33
|
+
end
|
34
|
+
|
35
|
+
return query.where("(#{@klass.from(query).select('COUNT(*)').to_sql}) = ?", hash.size)
|
36
|
+
.update_all(update_sqls.join(', '))
|
37
|
+
end
|
38
|
+
|
12
39
|
private
|
13
40
|
|
14
41
|
def on_duplicate_key_plus_sql( columns)
|
15
|
-
columns.lazy
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
42
|
+
columns.lazy.map(&method(:quote_column)).map{|s| "#{s} = #{s} + VALUES(#{s})" }.force.join(', ')
|
43
|
+
end
|
44
|
+
|
45
|
+
def quote_column(column)
|
46
|
+
@klass.connection.quote_column_name(column)
|
47
|
+
end
|
48
|
+
|
49
|
+
def sanitize(value)
|
50
|
+
@klass.connection.quote(value)
|
20
51
|
end
|
21
52
|
end
|
data/lib/atomically/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: atomically
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- khiav reoy
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-11-
|
11
|
+
date: 2018-11-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -94,6 +94,20 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 2.0.3
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: activerecord
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '3'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '3'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: activerecord-import
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
@@ -109,19 +123,19 @@ dependencies:
|
|
109
123
|
- !ruby/object:Gem::Version
|
110
124
|
version: 0.27.0
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
|
-
name:
|
126
|
+
name: rails_or
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
114
128
|
requirements:
|
115
129
|
- - ">="
|
116
130
|
- !ruby/object:Gem::Version
|
117
|
-
version:
|
131
|
+
version: 1.1.8
|
118
132
|
type: :runtime
|
119
133
|
prerelease: false
|
120
134
|
version_requirements: !ruby/object:Gem::Requirement
|
121
135
|
requirements:
|
122
136
|
- - ">="
|
123
137
|
- !ruby/object:Gem::Version
|
124
|
-
version:
|
138
|
+
version: 1.1.8
|
125
139
|
description: ''
|
126
140
|
email:
|
127
141
|
- mrtmrt15xn@yahoo.com.tw
|
@@ -149,6 +163,8 @@ files:
|
|
149
163
|
- gemfiles/5.2.gemfile
|
150
164
|
- lib/atomically.rb
|
151
165
|
- lib/atomically/active_record/extension.rb
|
166
|
+
- lib/atomically/patches/from.rb
|
167
|
+
- lib/atomically/patches/none.rb
|
152
168
|
- lib/atomically/query_service.rb
|
153
169
|
- lib/atomically/version.rb
|
154
170
|
homepage: https://github.com/khiav223577/atomically
|
@@ -171,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
171
187
|
version: '0'
|
172
188
|
requirements: []
|
173
189
|
rubyforge_project:
|
174
|
-
rubygems_version: 2.6
|
190
|
+
rubygems_version: 2.7.6
|
175
191
|
signing_key:
|
176
192
|
specification_version: 4
|
177
193
|
summary: ''
|