mercredi 6 avril 2016

Creating facade ideologically in Ruby

I'm trying to implement a Facade in ideologic Ruby while coming from Java. I can see that Rails' ActiveRecord is fond of using class methods for things like find_by(criteria) and does not use Repository pattern for that task.

My Facade wraps a specific webservice with several methods. My original idea was to make it's API similar to ActiveRecord (learning by imitation):

class MyEntity
  # ....

  def get_name
    @loaded_name + @loaded_surname
  end

  def delete
    @entity_access_service.delete(@id)
  end

  def save 
    @entity_access_service.save(@id, @loaded_name , @loaded_surname)
  end

  def self.find(id)
    data = @entity_access_service.get_data_for(id)
    MyEntity.new(data) #Or whatever way to populate my entity
  end
end

This, in theory, would work great:

e = MyEntity.find(10)
p e.get_name
e.delete

Or:

e = MyEntity.new(some stuff)
e.save

Question: For save and delete instance methods to work, I need to somehow get an instance of EntityAccessService. This instance should be mockable to test it in isolated environment. What is the correct way to do it?

I'm expecting my tests to look as simple as possible and without some weird hacks, as what I'm trying to implement seems fairly trivial.

I have thought of several options to do that:

  1. Having a class-level variable holding entity_access_service used by all of the entities created in application. In this case, where should I initialize this field? For example:

    class MyEntity
      @@entity_access_service = nil
    end
    
    # Somewhere else (where?):
    MyEntity.entity_access_service = MyEntityService.new(some_params_from_env)
    
    

    This way, in my tests I would have to initialize/mock it at start.

  2. Similar to 1 but initialize it in the class. This looks weird, especially if I know that my tests do not have required ENV params populated at all.

  3. Have an extra constructor/attribute to set the entity_service. This won't work, as save would not have this field initialized.

  4. Create a Repository class. This would work pretty ok, but seems to be not what Ruby people do.

Thanks in advance.

Aucun commentaire:

Enregistrer un commentaire