Module: ConstantTableSaver::ActiveRecord4ClassMethods

Defined in:
lib/constant_table_saver.rb

Instance Method Summary collapse

Instance Method Details

#_to_sql_with_binds(sql, binds) ⇒ Object



83
84
85
86
87
88
89
90
91
# File 'lib/constant_table_saver.rb', line 83

def _to_sql_with_binds(sql, binds)
  if sql.respond_to?(:to_sql)
    # an arel object
    connection.to_sql(sql, binds)
  else
    # a plain string
    sql
  end
end

#find_by_sql(sql, binds = []) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/constant_table_saver.rb', line 53

def find_by_sql(sql, binds = [])
  @find_by_sql ||= {
    :all   => all.to_sql,
    :id    => relation.where(relation.table[primary_key].eq(connection.substitute_at(columns_hash[primary_key], 1))).limit(1),
    :first => relation.order(relation.table[primary_key].asc).limit(1).to_sql,
    :last  => relation.order(relation.table[primary_key].desc).limit(1).to_sql,
  }

  if binds.empty?
    _sql = _to_sql_with_binds(sql, binds)

    if _sql == @find_by_sql[:all]
      return @cached_records ||= super(relation.to_sql).each(&:freeze)
    elsif _sql == @find_by_sql[:first]
      return [relation.to_a.first].compact
    elsif _sql == @find_by_sql[:last]
      return [relation.to_a.last].compact
    end

  elsif binds.length == 1 &&
        binds.first.first.is_a?(ActiveRecord::ConnectionAdapters::Column) &&
        binds.first.first.name == primary_key &&
        _to_sql_with_binds(sql, binds) == _to_sql_with_binds(@find_by_sql[:id], binds) # we have to late-render the find(id) SQL because mysql2 on 4.1 and later requires the bind variables to render the SQL, and errors out with a nil dereference otherwise
    @cached_records_by_id ||= relation.to_a.index_by {|record| record.id.to_param}
    return [@cached_records_by_id[binds.first.last.to_param]].compact
  end

  super
end

#relationObject



93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/constant_table_saver.rb', line 93

def relation
  super.tap do |s|
    class << s
      # we implement find_some here because we'd have to use partial string matching to catch
      # this case in find_by_sql, which would be ugly.  (we do the other cases in find_by_sql
      # because it's simpler & the only place to catch things like association find queries.)
      def find_some(ids)
        return super if @values.present? # special cases such as offset and limit
        ids.collect {|id| find_one(id)}
      end
    end
  end
end