Skip to content
This repository has been archived by the owner on Nov 28, 2022. It is now read-only.

Commit

Permalink
Merge pull request #6 from tricycle/ar-entity-builder
Browse files Browse the repository at this point in the history
Add ActiveRecord to Dry::Struct Entity builder
  • Loading branch information
samuelgiles authored Mar 13, 2019
2 parents 2a41244 + 25e9ecc commit 6169c09
Show file tree
Hide file tree
Showing 3 changed files with 122 additions and 1 deletion.
2 changes: 1 addition & 1 deletion .ruby-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.4.2
2.5.1
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
# frozen_string_literal: true

module CleanArchitecture
module Builders
# Helps to take an instance of an AR model and wrap it up in the given Entity
# Any columns from the AR model that do not directly map to an attribute on the Entity
# can be specified by overriding #attributes_for_entity.
class AbstractActiveRecordEntityBuilder
# @param [Class] A Dry::Struct based entity that this builder will construct instances of
def self.acts_as_builder_for_entity(entity_class)
define_method :entity_class do
entity_class
end

private :entity_class
end

# @param [ActiveRecord::Base] An ActiveRecord model to map to the entity
def initialize(ar_model_instance)
@ar_model_instance = ar_model_instance
end

def build
entity_class.new(all_attributes_for_entity)
end

private

attr_reader :ar_model_instance

def entity_attribute_names
@entity_attributes ||= entity_class.schema.keys
end

def ar_attributes_for_entity
attributes_for_entity = @ar_model_instance.attributes
symbolized_attributes_for_entity = Hash[attributes_for_entity.map{|(key, value)| [key.to_sym, value]}]
symbolized_attributes_for_entity.slice(*entity_attribute_names)
end

def attributes_for_entity
{}
end

def all_attributes_for_entity
ar_attributes_for_entity.merge(attributes_for_entity)
end
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
# frozen_string_literal: true

require 'clean_architecture/builders/abstract_active_record_entity_builder'

module CleanArchitecture
module Builders
describe AbstractActiveRecordEntityBuilder do
class ExampleModel
def age
25
end

def attributes
{
'forename' => 'Samuel',
'surname' => 'Giles',
'age' => 25
}
end
end

class ExampleEntitySchema
def keys
[:forename, :surname, :years_on_planet_earth]
end
end

class ExampleEntity
def initialize(attributes)
@attributes = attributes
end

def self.schema
ExampleEntitySchema.new
end
end

class ExampleBuilder < AbstractActiveRecordEntityBuilder
acts_as_builder_for_entity ExampleEntity

def attributes_for_entity
{
years_on_planet_earth: ar_model_instance.age
}
end
end

let(:builder) { ExampleBuilder.new(ar_model_instance) }
let(:ar_model_instance) { ExampleModel.new }

describe '#build' do
subject(:build) { builder.build }

let(:example_entity) { instance_double(ExampleEntity) }

before do
expect(ExampleEntity)
.to receive(:new)
.with(
forename: 'Samuel',
surname: 'Giles',
years_on_planet_earth: 25
)
.and_return(example_entity)
end

it { is_expected.to eq example_entity }
end
end
end
end

0 comments on commit 6169c09

Please sign in to comment.