Module: Reamaze::Opinionated::InstanceMethods

Defined in:
lib/opinionated.rb

Overview

Make methods available to ActiveRecord models in the instance context

Instance Method Summary collapse

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

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

we can’t use alias chaining because Rails loads method_missing dynamically



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

def method_missing(id, *args, &block)
  self.class.preferential_configuration.keys.each do |key|
    # checker
    match = /#{key}_(.+)\?/.match(id.to_s)
    return !!get_preferential(key, match[1], true) if match

    # setter
    match = /#{key}_(.+)=/.match(id.to_s)
    return set_preferential key, match[1], args[0], true if match

    # getter
    match = /#{key}_(.+)/.match(id.to_s)
    return get_preferential key, match[1], true if match
  end
  
  super
end

Instance Method Details

#get_preferential(preferential, name, do_postprocess = false) ⇒ Object

Raises:

  • (ArgumentError)


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
155
156
157
158
159
# File 'lib/opinionated.rb', line 117

def get_preferential(preferential, name, do_postprocess = false)
  preferential = Helpers.normalize(preferential)
  name = Helpers.normalize(name)

  # Check to make sure the preferential exists
  raise ArgumentError, "Preference #{preferential} not defined for class #{self.class}" \
    unless self.class.preferential_configuration.has_key?(preferential)
  
  configuration = self.class.preferential_configuration[preferential]
  definition = configuration.definitions[name]

  # Invoke the association
  prefs = self[preferential] if self[preferential]
  prefs = {} if prefs.blank?

  # Try to find what they are looking for
  pref = prefs[name]

  # If the pref isn't found, try to fallback on a default
  if pref.nil? and definition
    # TODO break all these nested if statements out into helper methods, i like prettier code
    # TODO raise an exception if we don't respond to default_through or the resulting object doesn't respond to the preferential
    if definition.has_default_through and respond_to?(definition.default_through) and (through = send(definition.default_through)).blank? == false
      value = through.send(preferential)[name]
    elsif definition.has_default_dynamic
      if definition.default_dynamic.instance_of?(Proc)
        value = definition.default_dynamic.call(self)
      else
        # TODO raise an exception if we don't respond to default_dynamic
        value = send(definition.default_dynamic)
      end
    elsif definition.has_default
      value = Marshal::load(Marshal.dump(definition.default)) # BUGFIX deep cloning default values
    else
      value = nil
    end
  else
    value = pref
  end

  value = definition.postprocess.call(value) if do_postprocess and definition and definition.has_postprocess
  value
end

#set_preferential(preferential, name, value, do_preprocess = false) ⇒ Object

Raises:

  • (ArgumentError)


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
# File 'lib/opinionated.rb', line 89

def set_preferential(preferential, name, value, do_preprocess = false)
  preferential = Helpers.normalize(preferential)
  name = Helpers.normalize(name)

  # Check to make sure the preferential exists
  raise ArgumentError, "Preference #{preferential} is not defined for class #{self.class}" \
    unless self.class.preferential_configuration.has_key?(preferential)
  
  configuration = self.class.preferential_configuration[preferential]
  definition = configuration.definitions[name]

  # Do preprocess here, type_check and validate can be done as AR validation in
  value = definition.preprocess.call(value) if do_preprocess and definition and definition.has_preprocess

  # Invoke the association
  prefs = ::Hash[self[preferential]] if self[preferential]

  if prefs.blank?
    send(preferential + '=', {name => value})
    prefs = send(preferential)
  else
    prefs[name] = value
    send(preferential + '=', prefs)
  end
  
  prefs[name]
end