unit testing - Creating facade idiomatically in Ruby -


i'm trying implement facade in idiomatic ruby while coming java. can see rails' activerecord fond of using class methods things find_by(criteria) , not use repository pattern task.

my facade wraps specific webservice several methods. original idea make it's api similar activerecord (learning 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 populate entity   end end 

this, in theory, work great:

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

or:

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

question: save , delete instance methods work, need somehow instance of entityaccessservice. instance should mockable test in isolated environment. correct way it?

i'm expecting tests simple possible , without weird hacks, i'm trying implement seems trivial.

i have thought of several options that:

  1. having class-level variable holding entity_access_service used of entities created in application. in case, should initialize field? example:

    class myentity   @@entity_access_service = nil end  # somewhere else (where?): myentity.entity_access_service = myentityservice.new(some_params_from_env) 

    this way, in tests have initialize/mock @ start.

  2. similar 1 initialize in class. looks weird, if know tests not have required env params populated @ all.

  3. have constructor/attribute set entity_service. won't work, save not have field initialized.

  4. create repository class. work pretty ok, seems not ruby people do.

following activerecord's example, can create method on class itself, or on base class other classes derived.

activerecord provides method activerecord::base.connection returns connection object models use access database. can similar:

class myentity     ....      def self.entity_access_service       # return service object     end      def self.find(id)         myentity.entity_access_service.get_data_for(id)         myentity.new(data) # or whatever way populate entity     end      def save()          myentity.entity_access_service.save(@id, @loadedname, @loadedsurname)     end end 

as far initialization goes, either have have initialization step in app (and test suite) service credentials read config files , passed myentity object, or entity_access_service method can lazily create object returns on first access using common ruby idiom:

def self.entity_access_service   @entity_access_service || = # build entity_access_service object end 

note that, wrapping class-level instance variables in class-level accessor methods, can avoid use of @@ recommended best practice.


Comments