class_loader 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -2,7 +2,7 @@ require 'rake_ext'
2
2
 
3
3
  project(
4
4
  name: "class_loader",
5
- version: "0.4.2",
5
+ version: "0.4.3",
6
6
  summary: "Automatically finds, loads and reloads Classes",
7
7
 
8
8
  author: "Alexey Petrushin",
data/lib/class_loader.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  raise 'ruby 1.9.2 or higher required!' if RUBY_VERSION < '1.9.2'
2
2
 
3
+ module ClassLoader
4
+ end
5
+
3
6
  %w(
4
7
  support
5
8
  file_system_adapter/camel_case_translator
@@ -1,44 +1,42 @@
1
- module ClassLoader
2
- class ChainedAdapter
3
- attr_accessor :adapters
1
+ class ClassLoader::ChainedAdapter
2
+ attr_accessor :adapters
4
3
 
5
- def initialize
6
- @adapters = []
7
- end
8
-
9
- %w(
10
- exist?
11
- read
12
- to_file_path
13
- to_class_name
14
- ).each do |method|
15
- define_method method do |*args|
16
- catch :found do
17
- adapters.each do |a|
18
- value = a.send method, *args
19
- throw :found, value if value
20
- end
21
- nil
4
+ def initialize
5
+ @adapters = []
6
+ end
7
+
8
+ %w(
9
+ exist?
10
+ read
11
+ to_file_path
12
+ to_class_name
13
+ ).each do |method|
14
+ define_method method do |*args|
15
+ catch :found do
16
+ adapters.each do |a|
17
+ value = a.send method, *args
18
+ throw :found, value if value
22
19
  end
20
+ nil
23
21
  end
24
22
  end
25
-
26
- def each_changed_class &block
27
- adapters.each{|a| a.each_changed_class &block}
28
- end
29
-
30
- def each_class &block
31
- adapters.each{|a| a.each_class &block}
32
- end
33
-
34
- def clear
35
- adapters.each{|a| a.clear}
36
- end
37
-
38
- def add_path *args
39
- adapters.each do |a|
40
- a.add_path *args if a.respond_to? :add_path
41
- end
23
+ end
24
+
25
+ def each_changed_class &block
26
+ adapters.each{|a| a.each_changed_class &block}
27
+ end
28
+
29
+ def each_class &block
30
+ adapters.each{|a| a.each_class &block}
31
+ end
32
+
33
+ def clear
34
+ adapters.each{|a| a.clear}
35
+ end
36
+
37
+ def add_path *args
38
+ adapters.each do |a|
39
+ a.add_path *args if a.respond_to? :add_path
42
40
  end
43
41
  end
44
42
  end
@@ -1,13 +1,15 @@
1
1
  require 'monitor'
2
2
 
3
+ warn 'ClassLoader: working in slow, debug mode with explicit tmp file generation!' if defined?(CLASS_LOADER_GENERATE_TMP_FILES)
4
+
3
5
  module ClassLoader
4
6
  @observers = []
5
7
  SYNC = Monitor.new
6
8
 
7
9
  class << self
8
- def loaded_classes; @loaded_classes ||= {} end
10
+ def loaded_classes; @loaded_classes ||= {} end
9
11
 
10
- def load_class namespace, const, reload = false
12
+ def load_class namespace, const, reload = false
11
13
  SYNC.synchronize do
12
14
  original_namespace = namespace
13
15
  namespace = nil if namespace == Object or namespace == Module
@@ -52,16 +54,16 @@ module ClassLoader
52
54
  end
53
55
  end
54
56
 
55
- def reload_class class_name
57
+ def reload_class class_name
56
58
  SYNC.synchronize do
57
59
  class_name = class_name.sub(/^::/, "")
58
60
  namespace = Module.namespace_for(class_name)
59
61
  name = class_name.sub(/^#{namespace}::/, "")
60
-
62
+
61
63
  # removing old class
62
64
  # class_container = (namespace || Object)
63
65
  # class_container.send :remove_const, name if class_container.const_defined? name
64
-
66
+
65
67
  return load_class namespace, name, true
66
68
  end
67
69
  end
@@ -131,6 +133,9 @@ module ClassLoader
131
133
  #
132
134
  attr_accessor :watch_interval
133
135
  def start_watching!
136
+ # reloading doesn works in debug mode, because we by ourself are generating tmp source files
137
+ return if defined?(CLASS_LOADER_GENERATE_TMP_FILES)
138
+
134
139
  unless @watching_thread
135
140
  @watching_thread = Thread.new do
136
141
  while true
@@ -169,8 +174,25 @@ module ClassLoader
169
174
  def load class_name, const
170
175
  script = adapter.read class_name
171
176
  script = wrap_inside_namespace Module.namespace_for(class_name), script
172
- file_path = adapter.to_file_path(class_name)
173
- eval script, TOPLEVEL_BINDING, file_path
177
+ file_path = adapter.to_file_path(class_name)
178
+
179
+ # sometimes we need to generate file explicitly
180
+ # for example evaluated code will not be shown in Ruby coverage tool
181
+ unless defined?(CLASS_LOADER_GENERATE_TMP_FILES)
182
+ eval script, TOPLEVEL_BINDING, file_path
183
+ else
184
+ if file_path =~ /\.rb$/
185
+ tmp_file_path = file_path.sub /\.rb$/, '.cltmp.rb'
186
+ begin
187
+ File.open(tmp_file_path, "w"){|f| f.write(script)}
188
+ Kernel.load tmp_file_path
189
+ ensure
190
+ File.delete tmp_file_path if defined?(CLASS_LOADER_CLEAN) and ::File.exist?(tmp_file_path)
191
+ end
192
+ else
193
+ eval script, TOPLEVEL_BINDING, file_path
194
+ end
195
+ end
174
196
  end
175
197
 
176
198
  def raise_without_self exception, message
@@ -1,141 +1,139 @@
1
- module ClassLoader
2
- class FileSystemAdapter
3
- attr_reader :translator
4
-
5
- def initialize class_name_translator
6
- @translator = class_name_translator
7
- @paths, @watched_paths, @file_name_cache = [], [], {}
8
- @watched_files, @first_check = {}, true
9
- end
10
-
11
- def exist? class_name
12
- !!to_file_path(class_name)
13
- end
14
- alias_method :exists?, :exist?
15
-
16
- def read class_name
17
- file_path = to_file_path class_name
18
- return nil unless file_path
19
-
20
- if file_path =~ /\.rb$/
21
- File.open(file_path){|f| f.read}
22
- else
23
- "module #{class_name}; end;"
24
- end
25
- end
1
+ class ClassLoader::FileSystemAdapter
2
+ attr_reader :translator
3
+
4
+ def initialize class_name_translator
5
+ @translator = class_name_translator
6
+ @paths, @watched_paths, @file_name_cache = [], [], {}
7
+ @watched_files, @first_check = {}, true
8
+ end
9
+
10
+ def exist? class_name
11
+ !!to_file_path(class_name)
12
+ end
13
+ alias_method :exists?, :exist?
14
+
15
+ def read class_name
16
+ file_path = to_file_path class_name
17
+ return nil unless file_path
26
18
 
27
- def to_file_path class_name
28
- file_path, exist = @file_name_cache[class_name] || []
29
- unless exist
30
- normalized_name = translator.to_file_path class_name
31
- file_path = catch :found do
32
- # files
33
- paths.each do |base|
34
- try = "#{base}/#{normalized_name}.rb"
35
- if File.exist? try
36
- throw :found, try
37
- end
38
- end
39
-
40
- # dirs
41
- paths.each do |base|
42
- try = "#{base}/#{normalized_name}"
43
- if File.exist? try
44
- throw :found, try
45
- end
19
+ if file_path =~ /\.rb$/
20
+ File.open(file_path){|f| f.read}
21
+ else
22
+ "module #{class_name}; end;"
23
+ end
24
+ end
25
+
26
+ def to_file_path class_name
27
+ file_path, exist = @file_name_cache[class_name] || []
28
+ unless exist
29
+ normalized_name = translator.to_file_path class_name
30
+ file_path = catch :found do
31
+ # files
32
+ paths.each do |base|
33
+ try = "#{base}/#{normalized_name}.rb"
34
+ if File.exist? try
35
+ throw :found, try
46
36
  end
47
-
48
- nil
49
37
  end
50
- @file_name_cache[class_name] = [file_path, true]
51
- end
52
- file_path
53
- end
54
-
55
- def to_class_name normalized_path
56
- raise "Internal error, file_name should be absolute path (#{normalized_path})!" unless normalized_path =~ /^\//
57
- raise "Internal error, file_name should be without .rb suffix (#{normalized_path})!" if normalized_path =~ /\.rb$/
58
-
59
- paths.each do |base_path|
60
- if normalized_path.start_with? base_path
61
- normalized_name = normalized_path.sub(base_path + '/', '')
62
- if translator.is_it_class? normalized_name
63
- return translator.to_class_name(normalized_name)
38
+
39
+ # dirs
40
+ paths.each do |base|
41
+ try = "#{base}/#{normalized_name}"
42
+ if File.exist? try
43
+ throw :found, try
64
44
  end
65
45
  end
46
+
47
+ nil
66
48
  end
67
- nil
49
+ @file_name_cache[class_name] = [file_path, true]
68
50
  end
51
+ file_path
52
+ end
53
+
54
+ def to_class_name normalized_path
55
+ raise "Internal error, file_name should be absolute path (#{normalized_path})!" unless normalized_path =~ /^\//
56
+ raise "Internal error, file_name should be without .rb suffix (#{normalized_path})!" if normalized_path =~ /\.rb$/
69
57
 
70
- def add_path base_path, watch = false
71
- base_path = File.expand_path(base_path)
72
- # raise "#{base_path} already added!" if paths.include? base_path
73
- unless paths.include? base_path
74
- paths << base_path
75
- watched_paths << base_path if watch
58
+ paths.each do |base_path|
59
+ if normalized_path.start_with? base_path
60
+ normalized_name = normalized_path.sub(base_path + '/', '')
61
+ if translator.is_it_class? normalized_name
62
+ return translator.to_class_name(normalized_name)
63
+ end
76
64
  end
77
65
  end
78
-
79
- def clear
80
- @paths, @watched_paths, @file_name_cache = [], [], {}
81
- @watched_files, @first_check = {}, true
82
- end
83
-
84
- def each_changed_class &block
85
- unless @first_check == @watched_paths
86
- @first_check = @watched_paths.clone
87
- each_watched_file{|file_path, file_name| remember_file file_path}
88
- else
89
- each_watched_file do |file_path, file_name|
90
- if file_changed? file_path
91
- remember_file file_path
92
-
93
- normalized_name = file_name.sub(/\.rb$/, "")
94
- block.call translator.to_class_name(normalized_name)
95
- end
96
- end
97
- end
66
+ nil
67
+ end
68
+
69
+ def add_path base_path, watch = false
70
+ base_path = File.expand_path(base_path)
71
+ # raise "#{base_path} already added!" if paths.include? base_path
72
+ unless paths.include? base_path
73
+ paths << base_path
74
+ watched_paths << base_path if watch
98
75
  end
99
-
100
- def each_class &block
101
- @paths.each do |base_path|
102
- Dir.glob("#{base_path}/**/*.rb").each do |file_path|
103
- normalized_path = file_path.sub(/\.rb$/, "")
76
+ end
77
+
78
+ def clear
79
+ @paths, @watched_paths, @file_name_cache = [], [], {}
80
+ @watched_files, @first_check = {}, true
81
+ end
82
+
83
+ def each_changed_class &block
84
+ unless @first_check == @watched_paths
85
+ @first_check = @watched_paths.clone
86
+ each_watched_file{|file_path, file_name| remember_file file_path}
87
+ else
88
+ each_watched_file do |file_path, file_name|
89
+ if file_changed? file_path
90
+ remember_file file_path
104
91
 
105
- normalized_name = normalized_path.sub(base_path + "/", '')
106
- class_name = translator.to_class_name(normalized_name)
107
- block.call class_name
92
+ normalized_name = file_name.sub(/\.rb$/, "")
93
+ block.call translator.to_class_name(normalized_name)
108
94
  end
95
+ end
96
+ end
97
+ end
98
+
99
+ def each_class &block
100
+ @paths.each do |base_path|
101
+ Dir.glob("#{base_path}/**/*.rb").each do |file_path|
102
+ normalized_path = file_path.sub(/\.rb$/, "")
103
+
104
+ normalized_name = normalized_path.sub(base_path + "/", '')
105
+ class_name = translator.to_class_name(normalized_name)
106
+ block.call class_name
109
107
  end
110
108
  end
111
-
112
- def each_watched_file &block
113
- @watched_paths.each do |base_path|
114
- Dir.glob("#{base_path}/**/*.rb").each do |file_path|
115
- file_name = file_path.sub(base_path + '/', '')
109
+ end
110
+
111
+ def each_watched_file &block
112
+ @watched_paths.each do |base_path|
113
+ Dir.glob("#{base_path}/**/*.rb").each do |file_path|
114
+ file_name = file_path.sub(base_path + '/', '')
116
115
 
117
- if translator.is_it_class? file_name
118
- block.call file_path, file_name
119
- end
116
+ if translator.is_it_class? file_name
117
+ block.call file_path, file_name
120
118
  end
121
119
  end
122
120
  end
121
+ end
122
+
123
+ def inspect
124
+ "FileSystemAdapter (#{@paths.join(', ')})"
125
+ end
126
+
127
+ protected
128
+ attr_reader :paths, :watched_paths, :watcher, :watched_files
123
129
 
124
- def inspect
125
- "FileSystemAdapter (#{@paths.join(', ')})"
126
- end
127
-
128
- protected
129
- attr_reader :paths, :watched_paths, :watcher, :watched_files
130
-
131
- def file_changed? file_path
132
- old_time = watched_files[file_path]
133
- old_time == nil or old_time != File.mtime(file_path)
134
- end
130
+ def file_changed? file_path
131
+ old_time = watched_files[file_path]
132
+ old_time == nil or old_time != File.mtime(file_path)
133
+ end
135
134
 
136
- def remember_file file_path
137
- watched_files[file_path] = File.mtime(file_path)
138
- end
139
-
140
- end
135
+ def remember_file file_path
136
+ watched_files[file_path] = File.mtime(file_path)
137
+ end
138
+
141
139
  end
@@ -1,18 +1,16 @@
1
- module ClassLoader
2
- class CamelCaseTranslator
3
- def self.to_class_name normalized_file_name
4
- raise "internall error, invalid format for #{normalized_file_name}!" if normalized_file_name =~ /^\//
5
- normalized_file_name.gsub('/', '::')
6
- end
7
-
8
- def self.to_file_path class_name
9
- raise "internall error, invalid format for #{class_name}!" if class_name =~ /^::/
10
- class_name.gsub('::', '/')
11
- end
12
-
13
- def self.is_it_class? normalized_file_name
14
- raise "internall error, invalid format for #{normalized_file_name}!" if normalized_file_name =~ /^\//
15
- normalized_file_name[0..0] =~ /[A-Z]/
16
- end
1
+ class ClassLoader::CamelCaseTranslator
2
+ def self.to_class_name normalized_file_name
3
+ raise "internall error, invalid format for #{normalized_file_name}!" if normalized_file_name =~ /^\//
4
+ normalized_file_name.gsub('/', '::')
5
+ end
6
+
7
+ def self.to_file_path class_name
8
+ raise "internall error, invalid format for #{class_name}!" if class_name =~ /^::/
9
+ class_name.gsub('::', '/')
10
+ end
11
+
12
+ def self.is_it_class? normalized_file_name
13
+ raise "internall error, invalid format for #{normalized_file_name}!" if normalized_file_name =~ /^\//
14
+ normalized_file_name[0..0] =~ /[A-Z]/
17
15
  end
18
16
  end
@@ -1,18 +1,16 @@
1
- module ClassLoader
2
- class UnderscoredTranslator
3
- def self.to_class_name normalized_file_name
4
- raise "internall error, invalid format for #{normalized_file_name}!" if normalized_file_name =~ /^\//
5
- normalized_file_name.camelize
6
- end
7
-
8
- def self.to_file_path class_name
9
- raise "internall error, invalid format for #{class_name}!" if class_name =~ /^::/
10
- class_name.underscore
11
- end
12
-
13
- def self.is_it_class? normalized_file_name
14
- raise "internall error, invalid format for #{normalized_file_name}!" if normalized_file_name =~ /^\//
15
- normalized_file_name[0..0] =~ /[a-z]/
16
- end
1
+ module ClassLoader::UnderscoredTranslator
2
+ def self.to_class_name normalized_file_name
3
+ raise "internall error, invalid format for #{normalized_file_name}!" if normalized_file_name =~ /^\//
4
+ normalized_file_name.camelize
5
+ end
6
+
7
+ def self.to_file_path class_name
8
+ raise "internall error, invalid format for #{class_name}!" if class_name =~ /^::/
9
+ class_name.underscore
10
+ end
11
+
12
+ def self.is_it_class? normalized_file_name
13
+ raise "internall error, invalid format for #{normalized_file_name}!" if normalized_file_name =~ /^\//
14
+ normalized_file_name[0..0] =~ /[a-z]/
17
15
  end
18
16
  end
@@ -0,0 +1,8 @@
1
+ desc "Cleans tmp files generated by ClassLoader in debug mode"
2
+ namespace :class_loader do
3
+ task :clean do
4
+ Dir['../**/*.cltmp.rb'].each do |path|
5
+ File.delete path
6
+ end
7
+ end
8
+ end
data/readme.md CHANGED
@@ -42,4 +42,4 @@ There's currently a known bug in Ruby 1.8.x - class loading isn't thread safe, s
42
42
 
43
43
  ## Please let me know about bugs and your proposals, there's the 'Issues' tab at the top, feel free to submit.
44
44
 
45
- Copyright (c) 2011 Alexey Petrushin http://4ire.net, released under the MIT license.
45
+ Copyright (c) Alexey Petrushin http://4ire.net, released under the MIT license.
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: class_loader
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-05-19 00:00:00.000000000 +04:00
12
+ date: 2011-07-02 00:00:00.000000000 +04:00
13
13
  default_executable:
14
14
  dependencies: []
15
15
  description:
@@ -26,6 +26,7 @@ files:
26
26
  - lib/class_loader/file_system_adapter/underscored_translator.rb
27
27
  - lib/class_loader/file_system_adapter.rb
28
28
  - lib/class_loader/support.rb
29
+ - lib/class_loader/tasks.rb
29
30
  - lib/class_loader.rb
30
31
  - spec/class_loader_spec/anonymous_class/AnonymousSpec/ClassInsideOfAnonymousClass.rb
31
32
  - spec/class_loader_spec/another_namespace/AnotherNamespace/NamespaceA.rb