Permalink
Browse files

Modified registry to look up models by convention

  • Loading branch information...
1 parent 8414f95 commit 160823bc78411206bf37b557d252daf672ede60e @elight committed Mar 15, 2013
Showing with 47 additions and 8 deletions.
  1. +22 −8 lib/edr/registry.rb
  2. +25 −0 spec/edr/registry_spec.rb
View
@@ -3,21 +3,37 @@
module Edr
class Registry
def self.define(&block)
- @@instance = self.new(&block)
+ @instance = self.new(&block)
end
def self.data_class_for(model_class)
- @@instance.data_class_for(model_class)
+ @instance.data_class_for(model_class)
end
def self.model_class_for(data_class)
- @@instance.model_class_for(data_class)
+ @instance.model_class_for(data_class)
end
+ def self.map_models_to_mappers
+ define unless @instance
+
+ ObjectSpace.each_object do |o|
@ruprict

ruprict May 6, 2013

FWIW, ObjectSpace is disabled in JRuby by default, so this won't work unless you enable it, which is (from what I can tell) a pretty big performance hit. https://github.com/jruby/jruby/wiki/PerformanceTuning#dont-enable-objectspace

@elight

elight May 25, 2013

Owner

Makes sense. But then you still need a way to locate arbitrary subclasses of AR::Base conforming to the naming conventions. JRuby may have it's own way to do this?

+ next unless o.is_a?(Class) &&
+ o.ancestors.include?(ActiveRecord::Base) &&
+ o.to_s =~ /Data$/
+ model_name = o.to_s.sub(/Data$/, "")
+
+ next unless Object.const_defined?(model_name)
+
+ model_class = Object.const_get(model_name)
+ @instance.map(model_class, o)
+ end
+ end
+
def initialize(&block)
@data_to_model_map = {}
@model_to_data_map = {}
- self.instance_eval &block
+ #self.instance_eval &block
@ruprict

ruprict Mar 21, 2013

So, how do you propose to do this in Rails? You can't just call map_model_to_mappers in an initializer without manually loading all the models first. If you take out the eval of the block, I have to do something like:

edr = Edr::Registry.define
edr.map Model, ModelData
... keep going for each class ...

in development which is kinda gross. I am fully prepared to not understand if there is a better way...

@elight

elight via email Mar 21, 2013

Owner
@elight

elight via email Mar 21, 2013

Owner
@ruprict

ruprict via email Mar 21, 2013

@elight

elight via email Mar 21, 2013

Owner
@ruprict

ruprict via email Mar 21, 2013

@elight

elight via email Mar 21, 2013

Owner
@elight

elight via email Mar 21, 2013

Owner
@elight

elight via email Mar 21, 2013

Owner
end
# the mapping is done by the class names, to avoid
@@ -31,14 +47,12 @@ def data_class_for model_class
data_class = @model_to_data_map[model_class.to_s]
return OpenStruct unless data_class
- data_class.constantize
+ Object.const_get(data_class)
end
def model_class_for data_class
model_class = @data_to_model_map[data_class.to_s]
- raise "No model class for #{data_class.to_s}" unless model_class
-
- model_class.constantize
+ model_class ? model_class.constantize : nil
end
private
View
@@ -0,0 +1,25 @@
+require 'spec_helper'
+require_relative '../../lib/edr/registry'
+
+describe Edr::Registry do
+ class HasAModelData < ActiveRecord::Base; end
+ class HasAModel; end
+
+ class DoesntHaveAModelData < ActiveRecord::Base; end
+
+ context "defining domain model to active record mappings" do
+ subject { Edr::Registry }
+
+ before do
+ subject.map_models_to_mappers
+ end
+
+ it "maps every AR::Base with a class name ending in 'Data' to a domain model class with the same name less 'Data'" do
+ expect(subject.model_class_for(HasAModelData)).to eq(HasAModel)
+ end
+
+ it "does not map an AR::Base ending in 'Data' to a domain model if none exist with the same name less 'Data'" do
+ expect(subject.model_class_for(DoesntHaveAModelData)).to be_nil
+ end
+ end
+end

0 comments on commit 160823b

Please sign in to comment.