Module: LunaPark::Extensions::Dsl::Attributes

Includes:
PredicateAttrAccessor, TypedAttrAccessor
Included in:
LunaPark::Entities::Attributable, Values::Attributable
Defined in:
lib/luna_park/extensions/dsl/attributes.rb

Overview

class-level mixin

Examples:

class Elephant
  include LunaPark::Extensions::Comparable   # required for Dsl::Attributes
  include LunaPark::Extensions::Serializable # required for Dsl::Attributes
  extend  LunaPark::Extensions::Dsl::Attributes

  # ...

  attr  :eyes_count                        # simple accessor registered as serializable and comparable attribute
  attr  :ears, Ears, :new                  # :new or any other class method that will construct Ear object
  attr  :defeat_enemies, comparable: false # will not be used in compasrion via `#==``
  attr? :alive                             # will add predicate? method

  attr_accessor :smuggler

  # ...
end

e1 = Elephant.new(eyes_count: 1, ears: { left: true, right: true }, defeat_enemies: 228, alive: true, smuggler: true)
e2 = Elephant.new(eyes_count: 1, ears: { left: true, right: true }, defeat_enemies: 0, alive: true, smuggler: false)
e3 = Elephant.new(eyes_count: 2, ears: { left: true, right: true }, defeat_enemies: 0, alive: true, smuggler: true)

e1 == e2 # => true  (comparsion disabled for #defeat_enemies and not registered for #smuggler)
e1 == e3 # => false (missmatch of #eyes_count)

e1.to_h # => { eyes_count: 1, ears: { left: true, right: true }, defeat_enemies: 228, alive: true }
        #    (omit #smuggler cause it's not registered for serialization)

e1.ears # => #<Ears left=true right=true>
e1.ears = { left: true, right: false }
e1.ears # => #<Ears left=true right=false>

e1.alive? # => true

Instance Method Summary collapse

Methods included from TypedAttrAccessor

#typed_attr_accessor, #typed_attr_writer

Methods included from PredicateAttrAccessor

#predicate_attr_accessor, #predicate_attr_reader

Instance Method Details

#attr(name, type = nil, type_meth = nil, comparable: true, array: false) ⇒ Hash(Symbol => Symbol)

define typed attr_accessor, register it for Extenions::Comparable, Extenions::Serializable

so it will be comparable using `#==`, `#eql?` and serializable using `#to_h`, `#serialize`
return Hash of defined methods `{ getter: :foo, setter: :foo= }`

Parameters:

  • name (Symbol)
  • type (Object) (defaults to: nil)

    any object that responds to method described in next param. Skip if you dont need stypification

  • type_meth (Symbol) (defaults to: nil)

    (call)

  • options (Hash)

    a customizable set of options

Returns:

  • (Hash(Symbol => Symbol))

    Hash of defined methods { :method_role => :method_name }; ‘{ getter: :foo }`



121
122
123
124
125
126
127
128
129
130
131
# File 'lib/luna_park/extensions/dsl/attributes.rb', line 121

def attr(name, type = nil, type_meth = nil, comparable: true, array: false)
  type_meth ||= DEFAULT_TYPE_METH
  attr_reader(name)

  serializable_attributes(name) if include?(Serializable)
  comparable_attributes(name)   if comparable && include?(Comparable)

  typed_attr_writer(name, type&.method(type_meth), is_array: array)

  { getter: name, setter: :"#{name}=" }
end

#attr?(*args, **options) ⇒ Hash(Symbol => Symbol)

.attrs that also adds ‘reader?`

return Hash of defined methods `{ getter: :foo, setter: :foo=, predicate }`

Returns:

  • (Hash(Symbol => Symbol))

    Hash of defined methods



73
74
75
76
77
78
79
80
81
# File 'lib/luna_park/extensions/dsl/attributes.rb', line 73

def attr?(*args, **options)
  defined_methods = attr(*args, **options)
  getter_name = defined_methods[:getter]

  protected(getter_name)
  attr_reader?(getter_name)

  defined_methods.merge(predicate: :"#{getter_name}?")
end

#attrs(*args, **options) ⇒ Array of Hash(Symbol => Symbol)

.attr with mass defining

Examples:

attrs name1, name2, name3, **attr_options
attrs name1, name2, name3, CallableType, **attr_options
attrs name1, name2, name3, Type, :type_method, **attr_options

Returns:

  • (Array of Hash(Symbol => Symbol))

    Hash of defined methods



92
93
94
95
96
97
98
99
100
101
102
103
104
105
# File 'lib/luna_park/extensions/dsl/attributes.rb', line 92

def attrs(*args, **options) # rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
  *names, type, type_meth = if args.all? { |arg| arg.is_a?(Symbol) }
                              [*args, nil, nil]
                            elsif args[0..-2].all? { |arg| arg.is_a?(Symbol) }
                              [*args, DEFAULT_TYPE_METH]
                            elsif args[0..-3].all? { |arg| arg.is_a?(Symbol) } && args.last.is_a?(Symbol)
                              args
                            else
                              raise ArgumentError, 'must be (*names) | ' \
                                '(*names, type) | (*names, type, type_meth)'
                            end

  names.map { |name| attr name, type, type_meth, **options }
end

#attrs?(*args, **options) ⇒ Array of Hash(Symbol => Symbol)

.attr that also adds ‘reader?`

Returns:

  • (Array of Hash(Symbol => Symbol))

    Hash of defined methods



58
59
60
61
62
63
64
65
66
# File 'lib/luna_park/extensions/dsl/attributes.rb', line 58

def attrs?(*args, **options)
  defined_methods_arr = attrs(*args, **options)
  getter_names = defined_methods_arr.map { |r| r[:getter] }

  protected(*getter_names)
  attr_reader?(*getter_names)

  defined_methods_arr.map { |r| r.merge(predicate: :"#{r[:getter]}?") }
end