Module: ActiveRecord::Refined::Writes

Defined in:
lib/active_record/refined.rb

Overview

The writing statements, which live on Relation rather than in QueryMethods. What a block adds here is the one thing their arguments cannot carry: a value worked out from the row rather than given.

Instance Method Summary collapse

Instance Method Details

#update_all(updates = nil, &block) ⇒ Object

UPDATE, from a block that gives a hash of column to value, where a value may be an expression built from the row: { likes: :likes + 1 }. Without a block it is Active Record's own, where likes: :likes sets the column to the symbol.

Examples:

Post.where { :published == true }.update_all { { likes: :likes + 1 } }
Post.update_all { { title: upper(:title) } }

Yield Returns:

  • (Hash{Symbol => Object})


1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
# File 'lib/active_record/refined.rb', line 1219

def update_all(updates = nil, &block)
  return super(updates) unless block
  if updates
    raise ArgumentError, "update_all takes updates or a block, not both"
  end
  result = evaluate_block(&block)
  unless result.is_a?(::Hash)
    raise ArgumentError, "the block gives update_all a hash of column => value"
  end
  super(result.transform_values { |value| to_arel_field(value) })
end

#upsert_all(attributes, **options, &block) ⇒ Object

INSERT ... ON CONFLICT DO UPDATE, with a block for what happens to a row that is already there: a hash of column to value, where BlockContext#excluded is the row that could not be inserted. Takes the block or on_duplicate:, not both. upsert_all's on_duplicate takes SQL text and nothing else, so this is the one place the DSL writes the SQL out itself rather than handing Arel a tree.

Examples:

Tally.upsert_all(rows, unique_by: :page) { { hits: :hits + excluded(:hits) } }

Yield Returns:

  • (Hash{Symbol => Object})


1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
# File 'lib/active_record/refined.rb', line 1242

def upsert_all(attributes, **options, &block)
  return super(attributes, **options) unless block
  if options.key?(:on_duplicate)
    raise ArgumentError, "upsert_all takes on_duplicate: or a block, not both"
  end
  result = evaluate_block(&block)
  unless result.is_a?(::Hash)
    raise ArgumentError, "the block gives upsert_all a hash of column => value"
  end
  if result.empty?
    raise ArgumentError, "the block gives upsert_all at least one column to set"
  end
  super(attributes, on_duplicate: Arel.sql(set_clause(result)), **options)
end