Class: Atomically::QueryService
- Inherits:
-
Object
- Object
- Atomically::QueryService
- Defined in:
- lib/atomically/query_service.rb
Constant Summary collapse
- DEFAULT_CONFLICT_TARGETS =
[:id].freeze
Instance Method Summary collapse
- #create_or_plus(columns, data, update_columns, conflict_target: DEFAULT_CONFLICT_TARGETS) ⇒ Object
-
#decrement_unsigned_counters(counters) ⇒ Object
Parameters.
-
#initialize(klass, relation: nil, model: nil) ⇒ QueryService
constructor
A new instance of QueryService.
-
#pay_all(hash, update_columns, primary_key: :id) ⇒ Object
{ id => pay_count }.
- #update(attrs, options = {}) ⇒ Object
- #update_all(expected_size, *args) ⇒ Object
- #update_all_and_get_ids(*args) ⇒ Object
Constructor Details
#initialize(klass, relation: nil, model: nil) ⇒ QueryService
Returns a new instance of QueryService.
15 16 17 18 19 |
# File 'lib/atomically/query_service.rb', line 15 def initialize(klass, relation: nil, model: nil) @klass = klass @relation = relation || @klass @model = model end |
Instance Method Details
#create_or_plus(columns, data, update_columns, conflict_target: DEFAULT_CONFLICT_TARGETS) ⇒ Object
21 22 23 |
# File 'lib/atomically/query_service.rb', line 21 def create_or_plus(columns, data, update_columns, conflict_target: DEFAULT_CONFLICT_TARGETS) @klass.import(columns, data, on_duplicate_key_update: on_duplicate_key_plus_sql(update_columns, conflict_target)) end |
#decrement_unsigned_counters(counters) ⇒ Object
Parameters
-
counters
- A Hash containing the names of the fields to update as keys and the amount to update the field by as values.
70 71 72 73 74 75 76 77 |
# File 'lib/atomically/query_service.rb', line 70 def decrement_unsigned_counters(counters) result = open_update_all_scope do counters.each do |field, amount| where("#{field} >= ?", amount).update("#{field} = #{field} - ?", amount) if amount > 0 end end return (result == 1) end |
#pay_all(hash, update_columns, primary_key: :id) ⇒ Object
{ id => pay_count }
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/atomically/query_service.rb', line 25 def pay_all(hash, update_columns, primary_key: :id) # { id => pay_count } return 0 if hash.blank? update_columns = update_columns.map(&method(:quote_column)) query = hash.inject(@klass.none) do |relation, (id, pay_count)| condition = @relation.where(primary_key => id) update_columns.each{|s| condition = condition.where("#{s} >= ?", pay_count) } next relation.or(condition) end raw_when_sql = hash.map{|id, pay_count| "WHEN #{sanitize(id)} THEN #{sanitize(-pay_count)}" }.join("\n") no_var_in_sql = true if update_columns.size == 1 or adapter_check_service.pg? update_sqls = update_columns.map.with_index do |column, idx| if no_var_in_sql value = "(\nCASE #{quote_column(primary_key)}\n#{raw_when_sql}\nEND)" else value = idx == 0 ? "(@change := \nCASE #{quote_column(primary_key)}\n#{raw_when_sql}\nEND)" : '@change' end next "#{column} = #{column} + #{value}" end return where_all_can_be_updated(query, hash.size).update_all(update_sqls.join(', ')) end |
#update(attrs, options = {}) ⇒ Object
54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/atomically/query_service.rb', line 54 def update(attrs, = {}) from = [:from] || :not_set success = update_and_return_number_of_updated_rows(attrs, from) == 1 if success assign_without_changes(attrs) @model.send(:clear_attribute_changes, @model.changes.keys) end return success end |
#update_all(expected_size, *args) ⇒ Object
50 51 52 |
# File 'lib/atomically/query_service.rb', line 50 def update_all(expected_size, *args) where_all_can_be_updated(@relation, expected_size).update_all(*args) end |
#update_all_and_get_ids(*args) ⇒ Object
79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
# File 'lib/atomically/query_service.rb', line 79 def update_all_and_get_ids(*args) if adapter_check_service.pg? scope = UpdateAllScope::UpdateAllScope.new(model: @model, relation: @relation.where('')) scope.update(*args) return @klass.connection.execute("#{scope.to_sql} RETURNING id", "#{@klass} Update All").map{|s| s['id'].to_i } end ids = nil id_column = quote_column_with_table(:id) @klass.transaction do @relation.connection.execute('SET @ids := NULL') @relation.where("((@ids := CONCAT_WS(',', #{id_column}, @ids)) IS NOT NULL)").update_all(*args) # 撈出有真的被更新的 id,用逗號串在一起 ids = @klass.from(Arel.sql('DUAL')).pluck(Arel.sql('@ids')).first end return ids.try{|s| s.split(',').map(&:to_i).uniq.sort } || [] # 將 id 從字串取出來 @id 的格式範例: '1,4,12' end |