Module: Piggyback::ClassMethods

Defined in:
lib/piggyback.rb

Instance Method Summary collapse

Instance Method Details

#define_attribute_methodsObject



11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/piggyback.rb', line 11

def define_attribute_methods
  @attribute_methods_mutex.synchronize do
    return if attribute_methods_generated?
  
    columns = []
  
    piggyback_attributes.values.each do |attribute|

      if column = attribute.column
        columns_hash[attribute.name] = column
        columns << attribute.name
      end

      if klass = attribute.serialized_class
        serialized_attributes[attribute.name] = klass
      end        
    end
  
    # This stunt is to call "super.super"
    _define_attribute_methods = ActiveModel::AttributeMethods::ClassMethods::instance_method(:define_attribute_methods)
    _define_attribute_methods.bind(self).call(columns)

  end
  super
end

#piggyback(*attr_names) ⇒ Object



74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/piggyback.rb', line 74

def piggyback(*attr_names)
  
  options = attr_names.extract_options!

  attr_names.flatten!
  attr_names.map!(&:to_s)

  piggybacks = []
  attributes = []
  joins      = []

  if attr_names.empty?
    
    if options.has_key?(:from)          
      froms = Array.wrap(options[:from])          
      piggybacks = piggyback_attributes.values.select do |attribute|
        froms.include?(attribute.reflection.name)
      end          
    else
      piggybacks = piggyback_attributes.values
    end

  else
    attr_names.uniq.each do |attr_name|
      if attribute = piggyback_attributes[attr_name]
        piggybacks << attribute
      elsif attribute = arel_table[attr_name]
        attributes << attribute
      else
        raise "Unkown attribute #{attr_name}"
      end        
    end
  end

  if scoped.select_values.none? && attributes.empty?
    attributes << "#{quoted_table_name}.*" 
  end

  piggybacks.each do |attribute|
    attributes << attribute.select
    joins      << attribute.reflection.name
  end

  context = select(attributes)
  
  if joins.any?
    dependency = ActiveRecord::Associations::JoinDependency.new(self, joins.uniq.compact, [])
    joins = dependency.join_associations.each{ |assoc| assoc.join_type = Arel::OuterJoin }
    context.joins(joins)
  else
    context        
  end      
end

#piggyback_attr(*attributes) ⇒ Object

Raises:

  • (ArgumentError)


37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/piggyback.rb', line 37

def piggyback_attr(*attributes)
  options = attributes.extract_options!
  options.assert_valid_keys(:from)

  raise ArgumentError, "No attributes specified for piggybacking"  if attributes.empty?      
  
  from = options[:from]
  reflection = reflect_on_association(from)
  
  raise ArgumentError, "#{self.name} has no association #{from.inspect}"              if reflection.nil?      
  raise ArgumentError, "Piggyback only supports belongs_to and has_one associations"  if reflection.collection?
      
  attributes.each do |attribute|
    case attribute
      
    when Symbol
      add_piggyback_attribute(reflection, attribute)

    when Hash
      mappings = attribute
      mappings.each do |attribute, mapping|
        case mapping

        when Symbol
          add_piggyback_attribute(reflection, attribute, source: mapping)

        when String
          add_piggyback_attribute(reflection, attribute, sql: mapping)

        when Array
          add_piggyback_attribute(reflection, attribute, sql: mapping.first, source: mapping.last)
        end
      end
    end        
  end
end