Class: ActiveRecord::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/rails/pattern_matching.rb

Instance Method Summary collapse

Instance Method Details

#deconstruct_keys(keys) ⇒ Object

Returns a hash of attributes for the given keys. Provides the pattern matching interface for matching against hash patterns. For example:

class Person < ActiveRecord::Base
end

def greeting_for(person)
  case person
  in { name: "Mary" }
    "Welcome back, Mary!"
  in { name: }
    "Welcome, stranger!"
  end
end

person = Person.new
person.name = "Mary"
greeting_for(person) # => "Welcome back, Mary!"

person = Person.new
person.name = "Bob"
greeting_for(person) # => "Welcome, stranger!"


49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/rails/pattern_matching.rb', line 49

def deconstruct_keys(keys)
  if keys
    # If we've been given keys, then we're going to filter down to just the
    # values that are being requested.
    keys.each_with_object({}) do |key, deconstructed|
      method = key.to_s

      # We don't need to worry about the case where the user provided a key
      # that doesn't match an attribute or association, because the match
      # will fail by virtue of there not being a key in the result hash.
      if attribute_method?(method)
        # Here we're pattern matching against an attribute method. We're
        # going to use the [] method so that we either get the value or
        # raise an error for a missing attribute in case it wasn't loaded.
        deconstructed[key] = public_send(method)
      elsif self.class.reflect_on_association(method)
        # Here we're going to pattern match against an association. We're
        # going to use the main interface for that association which can
        # be further pattern matched later.
        deconstructed[key] = public_send(method)
      end
    end
  else
    # If we haven't been given keys, then the user wants to grab up all of the
    # attributes and associations for this record.
    attributes.transform_keys(&:to_sym).merge!(
      self.class.reflect_on_all_associations.to_h do |reflection|
        [reflection.name, public_send(reflection.name)]
      end
    )
  end
end