Commit c7219e9d by Kirill Lashuk

Use ObjectSpace to locate models by their file names.

This approach eliminates necessity to guess model name by file name that allow to process models with any kind of non-standard capitalization in class and module names. Though, it still requires that underscored file name matches underscored model class name. If file is located not at the top level of models directory then we assume that model is either nested in the corresponding chain of modules or is not nested at all.
parent a43c08f0
...@@ -251,24 +251,19 @@ module AnnotateModels ...@@ -251,24 +251,19 @@ module AnnotateModels
models models
end end
# Retrieve the classes belonging to the model names we're asked to process # Retrieve model class from the given file.
# Check for namespaced models in subdirectories as well as models
# in subdirectories without namespacing.
def get_model_class(file) def get_model_class(file)
# this is for non-rails projects, which don't get Rails auto-require magic # this is for non-rails projects, which don't get Rails auto-require magic
require File.expand_path("#{model_dir}/#{file}") unless Module.const_defined?(:Rails) require File.expand_path("#{model_dir}/#{file}") unless Module.const_defined?(:Rails)
model = ActiveSupport::Inflector.camelize(file.gsub(/\.rb$/, '')) model_path = file.gsub(/\.rb$/, '')
parts = model.split('::') get_loaded_model(model_path) || get_loaded_model(model_path.split('/').last)
begin end
parts.inject(Object) {|klass, part| klass.const_get(part) }
rescue LoadError, NameError # Retrieve loaded model class by path to the file where it's supposed to be defined.
begin def get_loaded_model(model_path)
Object.const_get(parts.last) ObjectSpace.each_object(class << ActiveRecord::Base; self; end).detect do |c|
rescue LoadError, NameError ActiveSupport::Inflector.underscore(c) == model_path
Object.const_get(Module.constants.detect{|c|parts.last.downcase == c.downcase})
end
end end
end end
......
...@@ -44,48 +44,92 @@ EOS ...@@ -44,48 +44,92 @@ EOS
end end
describe "#get_model_class" do describe "#get_model_class" do
require "tmpdir"
module ::ActiveRecord module ::ActiveRecord
class Base class Base
end end
end end
def create(file, body="hi") def create(file, body="hi")
File.open(@dir + '/' + file, "w") do |f| file_path = File.join(AnnotateModels.model_dir, file)
FileUtils.mkdir_p(File.dirname(file_path))
File.open(file_path, "w") do |f|
f.puts(body) f.puts(body)
end end
end end
before :all do def check_class_name(file, class_name)
require "tmpdir" klass = AnnotateModels.get_model_class(file)
@dir = Dir.tmpdir + "/#{Time.now.to_i}" + "/annotate_models"
FileUtils.mkdir_p(@dir) klass.should_not == nil
AnnotateModels.model_dir = @dir klass.name.should == class_name
end
before :each do
AnnotateModels.model_dir = Dir.mktmpdir 'annotate_models'
end
it "should work" do
create('foo.rb', <<-EOS) create('foo.rb', <<-EOS)
class Foo < ActiveRecord::Base class Foo < ActiveRecord::Base
end end
EOS EOS
check_class_name 'foo.rb', 'Foo'
end
it "should not care about unknown macros" do
create('foo_with_macro.rb', <<-EOS) create('foo_with_macro.rb', <<-EOS)
class FooWithMacro < ActiveRecord::Base class FooWithMacro < ActiveRecord::Base
acts_as_awesome :yah acts_as_awesome :yah
end end
EOS EOS
check_class_name 'foo_with_macro.rb', 'FooWithMacro'
end
it "should find models with non standard capitalization" do
create('foo_with_capitals.rb', <<-EOS) create('foo_with_capitals.rb', <<-EOS)
class FooWithCAPITALS < ActiveRecord::Base class FooWithCAPITALS < ActiveRecord::Base
acts_as_awesome :yah
end end
EOS EOS
check_class_name 'foo_with_capitals.rb', 'FooWithCAPITALS'
end end
it "should work" do
klass = AnnotateModels.get_model_class("foo.rb") it "should find models inside modules" do
klass.name.should == "Foo" create('bar/foo_inside_bar.rb', <<-EOS)
module Bar
class FooInsideBar < ActiveRecord::Base
end
end
EOS
check_class_name 'bar/foo_inside_bar.rb', 'Bar::FooInsideBar'
end end
it "should not care about unknown macros" do
klass = AnnotateModels.get_model_class("foo_with_macro.rb") it "should find models inside modules with non standard capitalization" do
klass.name.should == "FooWithMacro" create('bar/foo_inside_capitals_bar.rb', <<-EOS)
module BAR
class FooInsideCapitalsBAR < ActiveRecord::Base
end
end
EOS
check_class_name 'bar/foo_inside_capitals_bar.rb', 'BAR::FooInsideCapitalsBAR'
end end
pending it "should find models with non standard capitalization" do
klass = AnnotateModels.get_model_class("foo_with_capitals.rb") it "should find non-namespaced models inside subdirectories" do
klass.name.should == "FooWithCAPITALS" create('bar/non_namespaced_foo_inside_bar.rb', <<-EOS)
class NonNamespacedFooInsideBar < ActiveRecord::Base
end
EOS
check_class_name 'bar/non_namespaced_foo_inside_bar.rb', 'NonNamespacedFooInsideBar'
end
it "should find non-namespaced models with non standard capitalization inside subdirectories" do
create('bar/non_namespaced_foo_with_capitals_inside_bar.rb', <<-EOS)
class NonNamespacedFooWithCapitalsInsideBar < ActiveRecord::Base
end
EOS
check_class_name 'bar/non_namespaced_foo_with_capitals_inside_bar.rb', 'NonNamespacedFooWithCapitalsInsideBar'
end end
end end
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment