Class: OccamsRecord::Results::Row

Inherits:
Object
  • Object
show all
Defined in:
lib/occams-record/results/row.rb

Overview

Abstract class for result rows.

Like ActiveRecord, Boolean columns have #field? methods. However, unlike ActiveRecord, other column types do NOT.

Constant Summary collapse

IDS_SUFFIX =
/_ids$/

Class Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(raw_values) ⇒ Row

Initialize a new result row.

Parameters:

  • raw_values (Array)

    array of raw values from db



35
36
37
38
# File 'lib/occams-record/results/row.rb', line 35

def initialize(raw_values)
  @raw_values = raw_values
  @cast_values = {}
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(name, *args, &block) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/occams-record/results/row.rb', line 115

def method_missing(name, *args, &block)
  model = self.class._model
  ex = NoMethodError.new("Undefined method `#{name}' for #{self.inspect}. Occams Record trace: #{self.class.eager_loader_trace}", name, args)
  raise ex if model.nil?

  name_str = name.to_s
  assoc = name_str.sub(IDS_SUFFIX, "").pluralize
  no_args = args.empty? && block.nil?

  if no_args and name_str =~ IDS_SUFFIX and can_define_ids_reader? assoc
    define_ids_reader! assoc
    send name
  elsif no_args and model.reflections.has_key? name_str
    raise MissingEagerLoadError.new(self, name)
  elsif no_args and model.columns_hash.has_key? name_str
    raise MissingColumnError.new(self, name)
  elsif self.class.active_record_fallback
    active_record_fallback(name, *args, &block)
  else
    raise ex
  end
end

Class Attribute Details

._modelObject

Returns the value of attribute _model.



15
16
17
# File 'lib/occams-record/results/row.rb', line 15

def _model
  @_model
end

.active_record_fallbackObject

If present, missing methods will be forwarded to the ActiveRecord model. :lazy allows lazy loading in AR, :strict doesn’t



25
26
27
# File 'lib/occams-record/results/row.rb', line 25

def active_record_fallback
  @active_record_fallback
end

.associationsObject

Array of associations names



14
15
16
# File 'lib/occams-record/results/row.rb', line 14

def associations
  @associations
end

.columnsObject

Array of column names



12
13
14
# File 'lib/occams-record/results/row.rb', line 12

def columns
  @columns
end

.eager_loader_traceObject

A trace of how this record was loaded (for debugging)



23
24
25
# File 'lib/occams-record/results/row.rb', line 23

def eager_loader_trace
  @eager_loader_trace
end

.model_nameObject

Name of Rails model



17
18
19
# File 'lib/occams-record/results/row.rb', line 17

def model_name
  @model_name
end

.primary_keyObject

Name of primary key column (nil if column wasn’t in the SELECT)



21
22
23
# File 'lib/occams-record/results/row.rb', line 21

def primary_key
  @primary_key
end

.table_nameObject

Name of originating database table



19
20
21
# File 'lib/occams-record/results/row.rb', line 19

def table_name
  @table_name
end

Instance Method Details

#==(obj) ⇒ Boolean

Returns true if the two objects are from the same table and have the same primary key.

Parameters:

Returns:

  • (Boolean)


56
57
58
59
60
61
62
# File 'lib/occams-record/results/row.rb', line 56

def ==(obj)
  super ||
    obj.is_a?(OccamsRecord::Results::Row) &&
    obj.class.table_name && obj.class.table_name == self.class.table_name &&
    (pkey1 = obj.class.primary_key) && (pkey2 = self.class.primary_key) &&
    obj.send(pkey1) == self.send(pkey2)
end

#[](attr) ⇒ Object

Hash-like accessor for attributes and associations.

Parameters:

  • attr (String|Symbol)

Returns:

  • (Object)


46
47
48
# File 'lib/occams-record/results/row.rb', line 46

def [](attr)
  respond_to?(attr) ? send(attr) : nil
end

#inspectString

Returns a string with the “real” model name and raw result values.

Weird note - if this string is longer than 65 chars it won’t be used in exception messages. bugs.ruby-lang.org/issues/8982

Returns:

  • (String)


109
110
111
112
# File 'lib/occams-record/results/row.rb', line 109

def inspect
  id = self.class.primary_key ? send(self.class.primary_key) : "none"
  "#<#{self.class.model_name || "Anonymous"} #{self.class.primary_key}: #{id}>"
end

#respond_to_missing?(name, _include_private = false) ⇒ Boolean

Returns:

  • (Boolean)


138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/occams-record/results/row.rb', line 138

def respond_to_missing?(name, _include_private = false)
  model = self.class._model
  return super if model.nil?

  name_str = name.to_s
  assoc = name_str.sub(IDS_SUFFIX, "").pluralize
  if name_str =~ IDS_SUFFIX and can_define_ids_reader? assoc
    true
  else
    super
  end
end

#to_h(symbolize_names: false, recursive: false) ⇒ Hash Also known as: to_hash, attributes

Return row as a Hash. By default the hash does NOT include associations.

Parameters:

  • symbolize_names (Boolean) (defaults to: false)

    if true, make Hash keys Symbols instead of Strings

  • recursive (Boolean) (defaults to: false)

    if true, include assiciations and them (and their associations) to hashes.

Returns:

  • (Hash)

    a Hash with String or Symbol keys



71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/occams-record/results/row.rb', line 71

def to_h(symbolize_names: false, recursive: false)
  hash = self.class.columns.each_with_object({}) { |col_name, acc|
    key = symbolize_names ? col_name.to_sym : col_name
    acc[key] = send col_name
  }

  recursive ? self.class.associations.each_with_object(hash) { |assoc_name, acc|
    key = symbolize_names ? assoc_name.to_sym : assoc_name
    assoc = send assoc_name
    acc[key] =
      if assoc.is_a? Array
        assoc.map { |x| x.to_h(symbolize_names: symbolize_names, recursive: true) }
      elsif assoc
        assoc.to_h(symbolize_names: symbolize_names, recursive: true)
      end
  } : hash
end

#to_sString

Returns the name of the model and the attributes.

Returns:

  • (String)


97
98
99
# File 'lib/occams-record/results/row.rb', line 97

def to_s
  "#{self.class.model_name || "Anonymous"}#{to_h(symbolize_names: true, recursive: false)}"
end