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



52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
# File 'lib/opinionated.rb', line 52

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)


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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/opinionated.rb', line 98

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].from_hstore 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.blank? 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)


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
# File 'lib/opinionated.rb', line 70

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].from_hstore] if self[preferential]

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