Module: Tablesmith::ActiveRecordSource

Includes:
HashRowsBase
Defined in:
lib/tablesmith/active_record_source.rb

Instance Method Summary collapse

Methods included from HashRowsBase

#create_headers, #normalize_keys, #row_values, #sort_columns

Instance Method Details

#build_columns(serializable_options) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/tablesmith/active_record_source.rb', line 26

def build_columns(serializable_options)
  @columns || begin
    @columns = []

    process_columns(serializable_options, first.class)

    include = serializable_options[:include]

    # swiped from activemodel-3.2.17/lib/active_model/serialization.rb
    unless include.is_a?(Hash)
      include = Hash[Array.wrap(include).map { |n| n.is_a?(Hash) ? n.to_a.first : [n, {}] }]
    end

    include.each do |association, opts|
      ar_class = first.class.reflections[association].klass
      process_columns(opts, ar_class)
    end
  end
end

#column_orderObject



11
12
13
# File 'lib/tablesmith/active_record_source.rb', line 11

def column_order
  @columns.map(&:full_unaliased_name)
end

#convert_item_to_hash_row(item) ⇒ Object



4
5
6
7
8
9
# File 'lib/tablesmith/active_record_source.rb', line 4

def convert_item_to_hash_row(item)
  item.reload unless item.new_record?
  hash = item.serializable_hash(process_all_columns(serializable_options))
  hash = fold_un_sourced_attributes_into_source_hash(first.class.name.underscore.to_sym, hash)
  flatten_inner_hashes(hash)
end

#de_alias_columns(only, ar_columns) ⇒ Object



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/tablesmith/active_record_source.rb', line 56

def de_alias_columns(only, ar_columns)
  only.map! do |attr|
    hits = ar_columns.select { |c| c.name =~ /#{attr.to_s.gsub(/_/, '.*')}/ }
    if hits.present?
      hit = hits[0] # TODO: support multiple hits
      if attr != hit
        hit.alias = attr
        hit.name
      else
        attr
      end
    else
      attr
    end
  end
end

#flatten_inner_hashes(hash) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
# File 'lib/tablesmith/active_record_source.rb', line 73

def flatten_inner_hashes(hash)
  new_hash = {}
  stack = hash.each_pair.to_a
  while ary = stack.shift
    key, value = ary
    if value.is_a?(Hash)
      value.each_pair do |assoc_key, assoc_value|
        new_hash["#{key}.#{assoc_key}"] = assoc_value.to_s
      end
    else
      new_hash[key] = value
    end
  end
  new_hash
end

#fold_un_sourced_attributes_into_source_hash(source_sym, hash) ⇒ Object

Top-level attributes aren’t nested in their own hash by default, this normalizes the overall hash by grouping those together:

converts “account”=>{“name”=>‘account’}

into {"supplier"=>{"name"=>'supplier'}, "account"=>{"name"=>'account'}}


94
95
96
97
98
99
# File 'lib/tablesmith/active_record_source.rb', line 94

def fold_un_sourced_attributes_into_source_hash(source_sym, hash)
  new_hash = {}
  new_hash[source_sym] = hash
  hash.delete_if { |k, v| new_hash[k] = v if v.is_a?(Hash) }
  new_hash
end

#process_all_columns(serializable_options) ⇒ Object



20
21
22
23
24
# File 'lib/tablesmith/active_record_source.rb', line 20

def process_all_columns(serializable_options)
  build_columns(serializable_options)

  serializable_options
end

#process_columns(serializable_options, ar_class) ⇒ Object



46
47
48
49
50
51
52
53
54
# File 'lib/tablesmith/active_record_source.rb', line 46

def process_columns(serializable_options, ar_class)
  only = serializable_options[:only]
  ar_columns = ar_class.columns.map { |c| Tablesmith::Column.new(name: c.name.to_s, source: ar_class.name.underscore) }
  @columns += ar_columns
  de_alias_columns(only, ar_columns) if only
  @columns += (serializable_options[:methods] || []).map do |meth_sym|
    Tablesmith::Column.new(name: meth_sym.to_s, source: ar_class.name.underscore)
  end
end

#serializable_optionsObject

allows overriding



16
17
18
# File 'lib/tablesmith/active_record_source.rb', line 16

def serializable_options
  {}
end