aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRobert2017-10-20 18:18:13 +0200
committerRobert2017-10-20 18:18:13 +0200
commitdce18aaeaf16a3109b801ba4cd8fd02d0cf564c0 (patch)
treeee256e930cd014ab507e2c18d170db318e398c5a
parent2315feae844a39ae9e86939b090bed0d2997f482 (diff)
downloadchouette-core-dce18aaeaf16a3109b801ba4cd8fd02d0cf564c0.tar.bz2
A promising approach to complete db stubbing
-rw-r--r--spec/models/faster_specs_spec.rb50
-rw-r--r--spec/support/faster/model_stubber.rb15
-rw-r--r--spec/support/faster/model_stubber/implementation.rb106
-rw-r--r--spec/support/faster/model_stubber/object_cache.rb23
4 files changed, 194 insertions, 0 deletions
diff --git a/spec/models/faster_specs_spec.rb b/spec/models/faster_specs_spec.rb
new file mode 100644
index 000000000..2c97d1055
--- /dev/null
+++ b/spec/models/faster_specs_spec.rb
@@ -0,0 +1,50 @@
+RSpec.describe 'Faster Specs', type: :faster do
+
+ shared_examples_for 'correct behavior' do
+
+ it 'finds workbench' do
+ expect( referential.workbench ).to eq(workbench)
+ end
+
+ it 'finds referentials' do
+ expect( workbench.referentials ).to eq([referential])
+ end
+
+ end
+
+ context 'in DB' do
+ let( :workbench ){ create :workbench }
+ let( :referential ){ create(:referential, workbench: workbench) }
+
+ it_behaves_like 'correct behavior'
+ end
+
+ context 'stubbed' do
+ let( :workbench ){ stub_model Workbench }
+ let( :referential ){ stub_model( Referential, workbench: workbench ) }
+
+ it_behaves_like 'correct behavior'
+
+ context 'workbench belongs to organisation' do
+ it 'workbench has no orgnaisation' do
+ expect( workbench.organisation ).to be_nil
+ end
+ it 'but it can be set' do
+ organisation = stub_model Organisation
+ workbench.organisation = organisation
+ expect( workbench.organisation ).to eq(organisation)
+ end
+ it 'and by setting it we get the reverse relation working' do
+ organisation = stub_model Organisation
+ workbench.organisation = organisation
+ expect( organisation.workbenches ).to be_eql([workbench])
+ end
+ it 'can also be constructed that way' do
+ organisation = stub_model Organisation
+ workbench = stub_model Workbench, organisation: organisation
+ expect( workbench.organisation ).to eq(organisation)
+ expect( organisation.workbenches ).to be_eql([workbench])
+ end
+ end
+ end
+end
diff --git a/spec/support/faster/model_stubber.rb b/spec/support/faster/model_stubber.rb
new file mode 100644
index 000000000..789f5c2d2
--- /dev/null
+++ b/spec/support/faster/model_stubber.rb
@@ -0,0 +1,15 @@
+require_relative 'model_stubber/implementation'
+
+module ModelStubber
+ def stub_model klass, **params
+ klass.new.tap do | model |
+ Implementation.new(model, params).setup
+ end
+ end
+end
+
+
+RSpec.configure do | conf |
+ # Empty Helper's cache before each example or create a helper?
+ conf.include ModelStubber, type: :faster
+end
diff --git a/spec/support/faster/model_stubber/implementation.rb b/spec/support/faster/model_stubber/implementation.rb
new file mode 100644
index 000000000..9ee1f417a
--- /dev/null
+++ b/spec/support/faster/model_stubber/implementation.rb
@@ -0,0 +1,106 @@
+require_relative './object_cache'
+
+module ModelStubber
+
+ # Get out of RSpec's example's namespace
+ class Implementation
+
+ attr_reader :model, :params
+
+ def initialize model, **params
+ @model = model
+ @params = params
+ end
+
+ def setup
+ ObjectCache.add_to_cache model
+ stub_all_relations
+ params.each(&method(:setup_att))
+ self
+ end
+
+
+ private
+
+ # Workers
+ def setup_att key, value
+ setup_reflection( model, key, value) && return
+ end
+
+ def setup_belongs_to reflection, model, key, value
+ model.stub(key){value}
+ has_manys =
+ value.class.reflect_on_all_associations(:has_many).select{|v| v.foreign_type == "#{model.class.name.underscore.pluralize}_type" }
+ has_manys.each do | has_many |
+ value.send( has_many.name ) << model
+ end
+ true
+ end
+
+ def setup_reflection model, key, value
+ case reflection = model.class.reflections[key.to_s]
+ when ActiveRecord::Reflection::BelongsToReflection
+ setup_belongs_to reflection, model, key, value
+ # when ActiveRecord::Reflection::HasManyReflection
+ # setup_has_many reflection, model, key, value
+ else
+ false
+ end
+ end
+
+
+ def stub_all_relations
+ reflections.each(&method(:stub_relation))
+ end
+
+ def stub_belongs_to name
+ singleton.send :attr_reader, name
+ define_singleton_method "#{name}=" do |value|
+ instance_variable_set("@#{name}", value)
+ has_manys =
+ value.class.reflect_on_all_associations(:has_many).select{|v| v.foreign_type == "#{self.class.name.underscore.pluralize}_type" }
+ has_manys.each do | has_many |
+ value.send( has_many.name ) << self
+ end
+ value
+ end
+ end
+
+ def stub_has_many name
+ empty = []
+ mystub(model, name){empty}
+ end
+
+ def stub_relation name, reflection
+ case reflection
+ when ActiveRecord::Reflection::BelongsToReflection
+ stub_belongs_to name
+ when ActiveRecord::Reflection::HasManyReflection
+ stub_has_many name
+ end
+
+ end
+
+ # Meta
+ def define_singleton_method name, &blk
+ singleton.module_eval do
+ define_method(name, &blk)
+ end
+ end
+ def mystub rcv, name, &blk
+ class << rcv; self end
+ .module_eval do
+ define_method(name, &blk)
+ end
+ end
+
+ # Lazy Values
+ def reflections
+ @__reflections__ ||= model.class.reflections
+ end
+
+ def singleton
+ @__singleton__ ||= class << model; self end
+ end
+ end
+end
diff --git a/spec/support/faster/model_stubber/object_cache.rb b/spec/support/faster/model_stubber/object_cache.rb
new file mode 100644
index 000000000..5749be76f
--- /dev/null
+++ b/spec/support/faster/model_stubber/object_cache.rb
@@ -0,0 +1,23 @@
+module ModelStubber
+ module ObjectCache extend self
+
+ def add_to_cache model
+ model.id = cache[model.class].keys.last.try(:succ) || 1
+ cache[model.class].update( model.id => model )
+ end
+
+ def empty_cache!
+ @__cache__ = _cache
+ end
+
+ private
+
+ def cache
+ @__cache__ ||= _cache
+ end
+ def _cache
+ Hash.new { |h, k| h[k] = {} }
+ end
+
+ end
+end