Class: ActiveRecord::Relation

Inherits:
Object
  • Object
show all
Defined in:
lib/monkey_patch_activerecord.rb

Overview

Patches for relation to allow back hooks into the ActiveRecord requesting name of table as a function of attributes.

Instance Method Summary collapse

Instance Method Details

#insert(values) ⇒ Object

Patches ActiveRecord‘s building of an insert statement to request of the model a table name with respect to attribute values being inserted.

The differences between this and the original code are small and marked with PARTITIONED comment.



105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/monkey_patch_activerecord.rb', line 105

def insert(values)
  primary_key_value = nil

  if primary_key && Hash === values
    primary_key_value = values[values.keys.find { |k|
      k.name == primary_key
    }]

    if !primary_key_value && connection.prefetch_primary_key?(klass.table_name)
      primary_key_value = connection.next_sequence_value(klass.sequence_name)
      values[klass.arel_table[klass.primary_key]] = primary_key_value
    end
  end

  im = arel.create_insert
  #
  # PARTITIONED ADDITION. get arel_table from class with respect to the
  # current values to placed in the table (which hopefully hold the values
  # that are used to determine the child table this insert should be
  # redirected to)
  #
  actual_arel_table = @klass.dynamic_arel_table(Hash[*values.map{|k,v| [k.name,v]}.flatten]) if @klass.respond_to?(:dynamic_arel_table)
  actual_arel_table = @table unless actual_arel_table
  im.into actual_arel_table

  conn = @klass.connection

  substitutes = values.sort_by { |arel_attr,_| arel_attr.name }
  binds       = substitutes.map do |arel_attr, value|
    [@klass.columns_hash[arel_attr.name], value]
  end

  substitutes.each_with_index do |tuple, i|
    tuple[1] = conn.substitute_at(binds[i][0], i)
  end

  if values.empty? # empty insert
    im.values = Arel.sql(connection.empty_insert_statement_value)
  else
    im.insert substitutes
  end

  conn.insert(
    im,
    'SQL',
    primary_key,
    primary_key_value,
    nil,
    binds)
end