Module: Lotus::Entity

Defined in:
lib/lotus/entity.rb,
lib/lotus/entity/dirty_tracking.rb

Overview

An object that is defined by its identity. See “Domain Driven Design” by Eric Evans.

An entity is the core of an application, where the part of the domain logic is implemented. It’s a small, cohesive object that expresses coherent and meaningful behaviors.

It deals with one and only one responsibility that is pertinent to the domain of the application, without caring about details such as persistence or validations.

This simplicity of design allows developers to focus on behaviors, or message passing if you will, which is the quintessence of Object Oriented Programming.

When a class includes ‘Lotus::Entity` it receives the following interface:

* #id
* #id=
* #initialize(attributes = {})

‘Lotus::Entity` also provides the `.attributes=` for defining attribute accessors for the given names.

If we expand the code above in **pure Ruby**, it would be:

Lotus::Model ships ‘Lotus::Entity` for developers’s convenience.

Lotus::Model depends on a narrow and well-defined interface for an Entity - ‘#id`, `#id=`, `#initialize(attributes={})`.If your object implements that interface then that object can be used as an Entity in the Lotus::Model framework.

However, we suggest to implement this interface by including ‘Lotus::Entity`, in case that future versions of the framework will expand it.

See Dependency Inversion Principle for more on interfaces.

Examples:

With Lotus::Entity

require 'lotus/model'

class Person
  include Lotus::Entity
  attributes :name, :age
end

Pure Ruby

class Person
  attr_accessor :id, :name, :age

  def initialize(attributes = {})
    @id, @name, @age = attributes.values_at(:id, :name, :age)
  end
end

See Also:

Since:

  • 0.1.0

Defined Under Namespace

Modules: ClassMethods, DirtyTracking

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.included(base) ⇒ Object

Inject the public API into the hosting class.

Examples:

With Object

require 'lotus/model'

class User
  include Lotus::Entity
end

With Struct

require 'lotus/model'

User = Struct.new(:id, :name) do
  include Lotus::Entity
end

Since:

  • 0.1.0



81
82
83
84
85
86
# File 'lib/lotus/entity.rb', line 81

def self.included(base)
  base.class_eval do
    extend ClassMethods
    attributes :id
  end
end

Instance Method Details

#==(other) ⇒ Object

Overrides the equality Ruby operator

Two entities are considered equal if they are instances of the same class and if they have the same #id.

Since:

  • 0.1.0



204
205
206
207
# File 'lib/lotus/entity.rb', line 204

def ==(other)
  self.class == other.class &&
     self.id == other.id
end

#attribute_namesObject

Return the set of attribute names

Examples:

require 'lotus/model'
class User
  include Lotus::Entity
  attributes :name
end

user = User.new(id: 23, name: 'Luca')
user.attribute_names # #<Set: {:id, :name}>

Since:

  • 0.5.1



239
240
241
# File 'lib/lotus/entity.rb', line 239

def attribute_names
  self.class.attributes
end

#initialize(attributes = {}) ⇒ Object

Defines a generic, inefficient initializer, in case that the attributes weren’t explicitly defined with ‘.attributes=`.

Parameters:

  • attributes (Hash) (defaults to: {})

    a set of attribute names and values

Raises:

  • NoMethodError in case the given attributes are trying to set unknown or private methods.

See Also:

  • attributes

Since:

  • 0.1.0



191
192
193
194
195
196
# File 'lib/lotus/entity.rb', line 191

def initialize(attributes = {})
  attributes.each do |k, v|
    setter = "#{ k }="
    public_send(setter, v) if respond_to?(setter)
  end
end

#inspectObject Also known as: to_s

Return the contents of the entity as a nicely formatted string.

Display all attributes of the entity for inspection (even if they are nil)

Examples:

require 'lotus/model'
class User
  include Lotus::Entity
  attributes :name, :email
end

user = User.new(id: 23, name: 'Luca')
user.inspect # #<User:0x007fa7eefe0b58 @id=nil @name="Luca" @email=nil>

Since:

  • 0.5.1



258
259
260
261
262
263
264
# File 'lib/lotus/entity.rb', line 258

def inspect
  attr_list = attribute_names.inject([]) do |res, name|
    res << "@#{name}=#{read_attribute(name).inspect}"
  end.join(' ')

  "#<#{self.class.name}:0x00#{(__id__ << 1).to_s(16)} #{attr_list}>"
end

#to_hObject

Return the hash of attributes

Examples:

require 'lotus/model'
class User
  include Lotus::Entity
  attributes :name
end

user = User.new(id: 23, name: 'Luca')
user.to_h # => { :id => 23, :name => "Luca" }

Since:

  • 0.2.0



222
223
224
# File 'lib/lotus/entity.rb', line 222

def to_h
  Hash[attribute_names.map { |a| [a, read_attribute(a)] }]
end

#update(attributes = {}) ⇒ Object

Set attributes for entity

Examples:

require 'lotus/model'
class User
  include Lotus::Entity
  attributes :name
end

user = User.new(name: 'Lucca')
user.update(name: 'Luca')
user.name # => 'Luca'

Since:

  • 0.2.0



282
283
284
285
286
# File 'lib/lotus/entity.rb', line 282

def update(attributes={})
  attributes.each do |attribute, value|
    public_send("#{attribute}=", value)
  end
end