Class: Shamu::Entities::Entity

Inherits:
Object
  • Object
show all
Extended by:
ActiveModel::Naming
Includes:
ActiveModel::Conversion, Attributes, Attributes::Equality, ToModelIdExtension::Models
Defined in:
lib/shamu/entities/entity.rb

Overview

An entity is an abstract set of data returned from a Services::Service describing the current state of an object.

Entities are immutable. They will not change for the duration of the request. Instead use a Services::Service to mutate the underlying data and request an updated copy of the Entity.

See Shamu::Entities for more on using entities.

Helper Methods

Entities can define helper methods to perform simple calculations or projections of it's data. They only rely on state available by other attribute projections. This makes the entity cacheable and serializable.

Why class instead of module?

The Entity class is ridiculously simple. It just mixes in a few modules and adds a few helper methods. It could just as easily been implemented as a module to mixin with POROs.

While modules are generally preferred for non-domain specific behaviors, in this case the purpose is to intentionally make it harder to mix the responsibilities of an Entity class with another object in your project. This tends to lead to better separation in your design.

Examples:


class LiveAccount < Shamu::Entities::Entity

  # Use an ActiveRecord User model for the actual data. Not accessible
  # to callers.
  model :user

  # Simple projections
  attribute :name, on: :user
  attribute :email, on: :user

  # Computed projections. Only calculated once, then cached in the
  # entity instance.
  attribute :signed_up_on do
    I18n.localize( user.created_at )
  end

  attribute :last_login_at do
    user..last
  end

  # Project another model
  model :contact

  # Project a JSON object using another entity class
  attribute :address, AddressEntity, on: :contact

  # Helper method
  def new_user?
    signed_up_on > 3.days.ago
  end
end

Direct Known Subclasses

Features::Toggle

Class Method Summary collapse

Instance Method Summary collapse

Methods included from ToModelIdExtension::Models

#to_model_id

Methods included from Attributes::Equality

#==, #hash

Methods included from Attributes

#[], #assign_attributes, association, associations, attribute, #attribute?, attributes, #initialize, #set?, #slice, #to_attributes

Class Method Details

.model(name, **args, &block) ⇒ self

Define a model attribute that the entity will project. Use additional Attributes.attribute calls to define the actual projections.

Model attributes are private and should never be exposed to any client from another domain. Instead project only the properties needed for the Entity's clients.

Examples:


class Account < Shamu::Entities::Entity
  model :user

  attribute :username, on: :user
  attribute :email, on: :user
end

Returns:

  • (self)


204
205
206
207
208
# File 'lib/shamu/entities/entity.rb', line 204

def model( name, **args, &block )
  attribute( name, **args, &block )
  attributes[name][:model] = true
  private name
end

.model_nameActiveModel::Name

Returns used by url_helpers etc when generating model specific names for this entity.

Returns:

  • (ActiveModel::Name)

    used by url_helpers etc when generating model specific names for this entity.



150
151
152
153
154
155
156
157
158
159
# File 'lib/shamu/entities/entity.rb', line 150

def model_name
  @model_name ||= begin
    base_name = name.sub /(::)?Entity$/, ""
    parts     = base_name.split "::"
    parts[-1] = parts[-1].singularize
    base_name = parts.join "::"

    ::ActiveModel::Name.new( self, nil, base_name )
  end
end

.null_entity(&block) ⇒ Class

Define custom default attributes for a NullEntity for this class.

Examples:


class Users::UserEntity < Shamu::Entities::Entity
  attribute :id
  attribute :name
  attribute :level

  null_entity do
    attribute :level do
      "Guest"
    end
  end
end

Returns:

  • (Class)

    the NullEntity class for the entity.



177
178
179
180
181
# File 'lib/shamu/entities/entity.rb', line 177

def null_entity( &block )
  null_class = ::Shamu::Entities::NullEntity.for( self )
  null_class.class_eval( &block ) if block_given?
  null_class
end

Instance Method Details

#empty?false Also known as: blank?

Returns real entities are not empty. See NullEntity.

Returns:

  • (false)

    real entities are not empty. See NullEntity.



96
97
98
# File 'lib/shamu/entities/entity.rb', line 96

def empty?
  false
end

#idObject



91
92
93
# File 'lib/shamu/entities/entity.rb', line 91

def id
  fail "No id attribute defined. Add `attribute :id, on: :record` to #{ self.class.name }"
end

#persisted?Boolean

Entities are always immutable - so they are considered persisted. Use a Services::ChangeRequest to back a form instead.

Returns:

  • (Boolean)


108
109
110
# File 'lib/shamu/entities/entity.rb', line 108

def persisted?
  true
end

#present?true

Returns the entity is present. See NullEntity.

Returns:

  • (true)

    the entity is present. See NullEntity.



102
103
104
# File 'lib/shamu/entities/entity.rb', line 102

def present?
  !empty?
end

#redact(attributes) ⇒ Entity

attributes redacted.

Returns:

  • (Entity)

    a modified version of the entity with the given



136
137
138
# File 'lib/shamu/entities/entity.rb', line 136

def redact( attributes )
  dup.redact!( attributes )
end

#redact!(*attributes) ⇒ Object

Redact attributes on the entity.

a list of attributes to set to nil or a hash of attributes with their values.

Parameters:

  • attributes (Array<Symbol>, Hash)

    to redact on the entity. Either



122
123
124
125
126
127
128
129
130
131
132
# File 'lib/shamu/entities/entity.rb', line 122

def redact!( *attributes )
  hash =
    if attributes.first.is_a?( Symbol )
      Hash[ attributes.zip( [ nil ] * attributes.length ) ]
    else
      attributes.first
    end

  assign_attributes hash
  self
end

#to_entityself

Returns:

  • (self)


113
114
115
# File 'lib/shamu/entities/entity.rb', line 113

def to_entity
  self
end