Module: ActiveRecord::HashlikeAccess

Defined in:
lib/active_record/hashlike_access.rb,
lib/active_record/hashlike_access/version.rb

Overview

The HashlikeAccess module simplifies querying for model records by providing find_by-equivalent access to records (or their values) via bracket syntax.

Constant Summary collapse

VERSION =
'0.1.1'.freeze

Instance Method Summary collapse

Instance Method Details

#[]Object

Finds a record by the previously-configured "lookup_fields" and calls the requested "response_method" on it.

Parameters:

  • * (Array)

    A list consisting of lookup values to match against the "lookup_fields" in search of a record. These are passed through, unaltered, to #hashlike_access_lookup.

Returns:

  • Returns either nil or the result of calling the "response_method" on the matched record.

Raises:

  • (ActiveRecord::RecordNotFound)


19
20
21
# File 'lib/active_record/hashlike_access.rb', line 19

def [](*)
  hashlike_access_lookup(*)&.public_send hashlike_access_config[:response_method]
end

#[]=(*args) ⇒ Object

Finds a record (as in #[]), and calls the "assignment_method" with the remaining param.

Parameters:

  • * (Array)

    A list consisting of lookup values as well as the actual assignment value. All but the last of these is passed through, unaltered, to #hashlike_access_lookup.

Returns:

  • As with all assignment methods, this returns the assignment value given.

Raises:

  • (NoMethodError, ActiveRecord::RecordInvalid, ActiveRecord::RecordNotSaved)


34
35
36
37
38
39
40
# File 'lib/active_record/hashlike_access.rb', line 34

def []=(*args)
  value = args.pop
  record = hashlike_access_lookup(*args) || return

  record.public_send hashlike_access_config[:assignment_method], value
  record.save!
end

#hashlike_access(to: :itself, by: nil, raise_if_not_found: false) ⇒ Hash (private)

The primary entrypoint for defining hash-like access behaviours.

Parameters:

  • [Symbol, (Hash)

    a customizable set of options

  • [true, (Hash)

    a customizable set of options

Returns:

  • (Hash)

    Returns the resulting hash-like access config.



60
61
62
63
64
65
66
67
# File 'lib/active_record/hashlike_access.rb', line 60

def hashlike_access(to: :itself, by: nil, raise_if_not_found: false)
  requested_config = { lookup_fields:      Array.wrap(by),
                       response_method:    to,
                       assignment_method:  :"#{to}=",
                       raise_if_not_found: raise_if_not_found }

  hashlike_access_config.merge! requested_config.compact_blank
end

#hashlike_access!(to: :itself, by: nil) ⇒ Hash (private)

A convenience method that calls #hashlike_access with raise_if_not_found: true.

Parameters:

  • [Symbol, (Hash)

    a customizable set of options

Returns:

  • (Hash)

    Returns the resulting hash-like access config.



81
82
83
# File 'lib/active_record/hashlike_access.rb', line 81

def hashlike_access!(to: :itself, by: nil)
  hashlike_access(to:, by:, raise_if_not_found: true)
end

#hashlike_access_configHash (private)

Returns the current hash-like access config, with sensible defaults if #hashlike_access has not been called.

Returns:

  • (Hash)

    Returns the current hash-like access config.



90
91
92
93
94
95
# File 'lib/active_record/hashlike_access.rb', line 90

def hashlike_access_config
  @hashlike_access_config ||= { lookup_fields:      Array.wrap(primary_key),
                                response_method:    :itself,
                                assignment_method:  nil,
                                raise_if_not_found: false }
end

#hashlike_access_lookup(*lookup_values) ⇒ ActiveRecord::Base? (private)

Finds a record using the configured "lookup_fields" matched to the provided "lookup_values".

Parameters:

  • lookup_values (Array)

    A list consisting of lookup values to match against the "lookup_fields" in search of a record.

Returns:

  • (ActiveRecord::Base, nil)

    Returns the matching record or nil if none was found and the "raise_if_not_found" config is false.

Raises:

  • (ActiveRecord::RecordNotFound)


107
108
109
110
111
112
# File 'lib/active_record/hashlike_access.rb', line 107

def hashlike_access_lookup(*lookup_values)
  record = find_by hashlike_access_config[:lookup_fields].zip(lookup_values).to_h
  raise ActiveRecord::RecordNotFound if record.blank? && hashlike_access_config[:raise_if_not_found]

  record
end