grape-reload 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 90005752e374515209acc7d30cf36d3e458645bd
4
- data.tar.gz: 54b9b236aaaadcd77d0a313a54c015730f81e648
3
+ metadata.gz: d23fb6507e6ffdadf978ae7cafa32ad6a49b7b09
4
+ data.tar.gz: 4cdb689e50c6f760afb8ea2fe660b3c4d3971cea
5
5
  SHA512:
6
- metadata.gz: 31c279a890f45ccf696a7ee25eaa7bafdea50cb99a8134aced2d3dd85a2d188b970444a5077068687bdcdf9a6c0111bd7789cdd946ff39f74e85e97dbc7ba94b
7
- data.tar.gz: 033a629434a32aae7503e27307ea69548d3b1ee7ce8b61e6de370c98c6f4894e9262ae8cba0b4aec4eaa107f9104f39d0b6681467017dd736661a67404ba91a9
6
+ metadata.gz: ee472baaa8f3a405e193940073a8ea0734501179432b18f33e6d625e58728d06cf884e318430581f720c6d2598d7ea5811b089a1fc5e650a62fef5d79fa5e846
7
+ data.tar.gz: e6d6ce030ee2f4f6aff852817276cb3597fb852cbf0c178505a069b622aa5cbf662049450e20e356cb66555288817d1be149d5b618da21fe586a87a647172b60
data/README.md CHANGED
@@ -1,3 +1,5 @@
1
+ [![Build Status](https://travis-ci.org/AlexYankee/grape-reload.svg?branch=master)](https://travis-ci.org/AlexYankee/grape-reload)
2
+ [![Gem Version](https://badge.fury.io/rb/grape-reload.svg)](http://badge.fury.io/rb/grape-reload)
1
3
  # Grape::Reload
2
4
 
3
5
  Expiremental approach for providing reloading of Grape-based rack applications in dev environment.
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require 'bundler/gem_tasks'
4
4
  # Default directory to look in is `/specs`
5
5
  # Run with `rake spec`
6
6
  RSpec::Core::RakeTask.new(:spec) do |task|
7
- task.rspec_opts = ['--color', '--format', 'nested']
7
+ task.rspec_opts = ['--color', '--format', 'progress']
8
8
  end
9
9
 
10
10
  task :default => :spec
@@ -0,0 +1,62 @@
1
+ # Ruby color support for Windows
2
+ # If you want colorize on Windows with Ruby 1.9, please use ansicon:
3
+ # https://github.com/adoxa/ansicon
4
+ # Other ways, add `gem 'win32console'` to your Gemfile.
5
+ if RUBY_PLATFORM =~ /mswin|mingw/ && RUBY_VERSION < '2.0' && ENV['ANSICON'].nil?
6
+ begin
7
+ require 'win32console'
8
+ rescue LoadError
9
+ end
10
+ end
11
+
12
+ ##
13
+ # Add colors
14
+ #
15
+ class String
16
+ # colorize(:red)
17
+ def colorize(args)
18
+ case args
19
+ when Symbol
20
+ Colorizer.send(args, self)
21
+ when Hash
22
+ Colorizer.send(args[:color], self, args[:mode])
23
+ end
24
+ end
25
+
26
+ # Used to colorize strings for the shell
27
+ class Colorizer
28
+ # Returns colors integer mapping
29
+ def self.colors
30
+ @_colors ||= {
31
+ :default => 9,
32
+ :black => 30,
33
+ :red => 31,
34
+ :green => 32,
35
+ :yellow => 33,
36
+ :blue => 34,
37
+ :magenta => 35,
38
+ :cyan => 36,
39
+ :white => 37
40
+ }
41
+ end
42
+
43
+ # Returns modes integer mapping
44
+ def self.modes
45
+ @_modes ||= {
46
+ :default => 0,
47
+ :bold => 1
48
+ }
49
+ end
50
+
51
+ # Defines class level color methods
52
+ # i.e Colorizer.red("hello")
53
+ class << self
54
+ Colorizer.colors.each do |color, value|
55
+ define_method(color) do |target, mode_name = :default|
56
+ mode = modes[mode_name] || modes[:default]
57
+ "\e[#{mode};#{value}m" << target << "\e[0m"
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
data/lib/grape/reload.rb CHANGED
@@ -1,2 +1,4 @@
1
1
  require "grape/reload/version"
2
- require "grape/reload/rack_builder"
2
+ require 'core_ext/string/colorize'
3
+ require 'core_ext/object_space'
4
+ require "grape/reload/rack_builder"
@@ -2,6 +2,11 @@ require_relative '../../ripper/extract_constants'
2
2
 
3
3
  module Grape
4
4
  module Reload
5
+ class UnresolvedDependenciesError < RuntimeError
6
+ def message; 'One or more unresolved dependencies found' end
7
+ end
8
+
9
+
5
10
  class DependencyMap
6
11
  extend Forwardable
7
12
  include TSort
@@ -32,11 +37,12 @@ module Grape
32
37
 
33
38
  def dependent_classes(loaded_file)
34
39
  classes = []
40
+ sorted = sorted_files
35
41
  cycle_classes = ->(file, visited_files = []){
36
42
  return if visited_files.include?(file)
37
43
  visited_files ||= []
38
44
  visited_files << file
39
- classes |= map[file][:declared] if file != loaded_file
45
+ classes |= map[file][:declared]
40
46
  map[file][:declared].map{|klass|
41
47
  file_class = map.each_pair
42
48
  .sort{|a1, a2|
@@ -110,6 +116,8 @@ module Grape
110
116
  unresolved_classes.each_pair do |klass, filenames|
111
117
  filenames.each {|filename| Grape::RackBuilder.logger.error("Unresolved const reference #{klass} from: #{filename}".colorize(:red)) }
112
118
  end
119
+
120
+ raise UnresolvedDependenciesError if unresolved_classes.any?
113
121
  end
114
122
  end
115
123
 
@@ -17,7 +17,7 @@ CLASS
17
17
  end
18
18
 
19
19
  def initialize(app)
20
- @app_klass = app.to_s
20
+ @app_klass = app
21
21
  end
22
22
 
23
23
  def call(*args)
@@ -48,12 +48,17 @@ METHOD
48
48
  def reinit!
49
49
  declaration = class_declaration.dup
50
50
  @class_decl = []
51
+ endpoints.each { |e| e.options[:app].reinit! if e.options[:app] }
51
52
  reset!
52
53
  declaration.each {|decl|
53
54
  send(decl[0],*deep_reconstantize.call(decl[1]),&decl[2])
54
55
  }
55
56
  change!
56
57
  end
58
+
59
+ def recursive_!
60
+
61
+ end
57
62
  private
58
63
  def class_declaration
59
64
  @class_decl ||= []
@@ -12,7 +12,7 @@ module Grape
12
12
  class << self
13
13
  [:error, :debug, :exception, :info, :devel].each do |level|
14
14
  define_method(level){|*args|
15
- puts level.to_s.upcase+": "+args.map{|a| a.to_s}.join(' ')+"\n"
15
+ # Silence all reloader output by default with stub
16
16
  }
17
17
  end
18
18
  end
@@ -75,10 +75,11 @@ module Grape
75
75
  if environment == 'development'
76
76
  r = Rack::Builder.new
77
77
  r.use Grape::ReloadMiddleware[reload_threshold]
78
- r.run m.app_class.constantize
78
+ r.run m.app_class
79
79
  map(m.mount_root) { run r }
80
80
  else
81
- map(m.mount_root) { run m.app_class.constantize }
81
+ app_klass = m.app_class.constantize
82
+ map(m.mount_root) { run app_klass }
82
83
  end
83
84
  end
84
85
  end
@@ -1,4 +1,4 @@
1
- require_relative '../../../lib/core_ext/object_space'
1
+
2
2
 
3
3
  module Grape
4
4
  module Reload
@@ -1,5 +1,5 @@
1
1
  module Grape
2
2
  module Reload
3
- VERSION = "0.0.2"
3
+ VERSION = "0.0.3"
4
4
  end
5
5
  end
@@ -14,12 +14,10 @@ module Grape
14
14
  def logger; Grape::RackBuilder.logger end
15
15
 
16
16
  def safe_load(file, options={})
17
- began_at = Time.now
18
17
  return unless options[:force] || file_changed?(file)
19
- # return require(file) if feature_excluded?(file)
20
18
 
21
19
  Storage.prepare(file) # might call #safe_load recursively
22
- logger.devel((file_new?(file) ? "loading" : "reloading") + "#{file}" )
20
+ logger.debug((file_new?(file) ? "loading" : "reloading") + "#{file}" )
23
21
  begin
24
22
  with_silence{ require(file) }
25
23
  Storage.commit(file)
@@ -102,23 +102,13 @@ class TraversingResult
102
102
  !variants.find{|v| result[:declared].include?(v) }.nil?
103
103
  }
104
104
 
105
- used = self.used.reject {|variants|
106
- !variants.find{|v| result[:declared].include?(v) }.nil?
107
- }
108
-
109
- if namespace
110
- ns_variants = [namespace+'::']
111
- full_namespace[0..-2].reverse.each{|ns| ns_variants << ns + '::' + ns_variants.last}
112
- used.each do |variants|
113
- # variants = variants.reject{ |v|
114
- # !ns_variants.find{|ns_part| v.start_with?(ns_part) }.nil?
115
- # }
116
- result[:used] = result[:used] << variants
117
- end
118
- else
119
- result[:used] = result[:used].concat(used)
105
+ used = self.used.reject {|variants| !variants.find{|v| result[:declared].include?(v) }.nil? }
106
+ if namespace.nil?
107
+ used = used.map {|variants| variants.map{|v| (v.start_with?('::') ? '' : (namespace || '') + '::') + v }}
120
108
  end
121
109
 
110
+ result[:used] = result[:used].concat(used)
111
+
122
112
  result
123
113
  end
124
114
  end
@@ -299,6 +289,7 @@ class ASTModule < ASTEntity
299
289
  }
300
290
  end
301
291
  def collect_constants(result, context)
292
+ result.declare_const(@module_name)
302
293
  result = result.nest(@module_name)
303
294
  context.module << @module_name
304
295
  super(result, context)
@@ -1,5 +1,7 @@
1
1
  module Test
2
2
  class Mount2 < Grape::API
3
-
3
+ get :test do
4
+ 'test'
5
+ end
4
6
  end
5
7
  end
@@ -1,12 +1,9 @@
1
1
  module Test
2
2
  class App2 < Grape::API
3
3
  format :txt
4
- mount Test::Mount2 => '/mounted'
5
- # mount Test::Mount10 => '/mounted2'
6
- mount Test::LibMount2 => '/lib_mounted'
7
- #changed: mount Test::LibMount2 => '/lib_mounted'
4
+ mount Test::Mount2 => '/mounted' #changed: mount Test::Mount2 => '/mounted2'
8
5
  get :test do
9
- 'test2 response' #changed: 'test2 response changed'
6
+ 'test2 response changed'
10
7
  end
11
8
  end
12
9
  end
@@ -10,11 +10,27 @@ describe Grape::Reload::DependencyMap do
10
10
  },
11
11
  'file2' => {
12
12
  declared: ['::Class2'],
13
- used: ['::Class1','::Class3'],
13
+ used: [['::Class1'],['::Class3']],
14
14
  },
15
15
  'file3' => {
16
16
  declared: ['::Class3'],
17
- used: ['::Class2'],
17
+ used: [['::Class1']],
18
+ },
19
+ }
20
+ }
21
+ let!(:wrong_class_map) {
22
+ {
23
+ 'file1' => {
24
+ declared: ['::Class1'],
25
+ used: [],
26
+ },
27
+ 'file2' => {
28
+ declared: ['::Class2'],
29
+ used: [['::Class1'],['::Class3']],
30
+ },
31
+ 'file3' => {
32
+ declared: ['::Class3'],
33
+ used: [['::Class5']],
18
34
  },
19
35
  }
20
36
  }
@@ -22,9 +38,13 @@ describe Grape::Reload::DependencyMap do
22
38
 
23
39
  it 'resolves dependent classes properly' do
24
40
  allow(dm).to receive(:map).and_return(file_class_map)
25
- # map = instance_double(Grape::Reload::DependencyMap)
26
- # allow(map).to receive(:map).and_return(file_class_map)
41
+ dm.resolve_dependencies!
27
42
 
28
43
  expect(dm.dependent_classes('file1')).to include('::Class2','::Class3')
29
44
  end
45
+
46
+ it "raises error if dependencies can't be resolved" do
47
+ allow(dm).to receive(:map).and_return(wrong_class_map)
48
+ expect { dm.resolve_dependencies! }.to raise_error(Grape::Reload::UnresolvedDependenciesError)
49
+ end
30
50
  end
@@ -6,6 +6,7 @@ describe Grape::Reload::Watcher do
6
6
  before(:example) do
7
7
  @app =
8
8
  Grape::RackBuilder.setup do
9
+ add_source_path File.expand_path('**.rb', APP_ROOT)
9
10
  add_source_path File.expand_path('**/*.rb', APP_ROOT)
10
11
  environment 'development'
11
12
  reload_threshold 0
@@ -42,6 +43,20 @@ describe Grape::Reload::Watcher do
42
43
  end
43
44
  end
44
45
 
46
+ it 'remounts class on different root' do
47
+ get '/test2/mounted/test'
48
+ expect(last_response).to succeed
49
+ expect(last_response.body).to eq('test')
50
+
51
+ with_changed_fixture 'app2/test2.rb' do
52
+ get '/test2/mounted/test'
53
+ expect(last_response).to_not succeed
54
+
55
+ get '/test2/mounted2/test'
56
+ expect(last_response).to succeed
57
+ end
58
+ end
59
+
45
60
  it 'reloads library file and reinits all affected APIs' do
46
61
  with_changed_fixture 'app1/test1.rb' do
47
62
  get '/test1/lib_mounted/lib_string'
@@ -53,6 +53,13 @@ CODE
53
53
  'test2 response'
54
54
  end
55
55
  end
56
+ module EmptyModule
57
+ end
58
+ end
59
+ class WithoutModule
60
+ def use_top_level
61
+ TopLevel.new
62
+ end
56
63
  end
57
64
  CODE
58
65
  }
@@ -83,15 +90,16 @@ CODE
83
90
  it 'extract consts from code2 correctly' do
84
91
  consts = Ripper.extract_constants(code2)
85
92
  expect(consts[:declared].flatten).to include(
86
- '::Test::App2'
93
+ '::Test::App2',
94
+ '::Test::EmptyModule'
87
95
  )
88
96
 
89
97
  expect(consts[:used].flatten).to include(
90
98
  '::Test::Mount2',
91
99
  '::Test::Mount10',
92
100
  '::Test::SomeAnotherEntity',
93
- '::SomeClass'
101
+ '::SomeClass',
102
+ '::TopLevel'
94
103
  )
95
-
96
104
  end
97
105
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grape-reload
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - AMar4enko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-18 00:00:00.000000000 Z
11
+ date: 2014-09-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: grape
@@ -208,6 +208,7 @@ files:
208
208
  - Rakefile
209
209
  - grape-reload.gemspec
210
210
  - lib/core_ext/object_space.rb
211
+ - lib/core_ext/string/colorize.rb
211
212
  - lib/grape/reload.rb
212
213
  - lib/grape/reload/dependency_map.rb
213
214
  - lib/grape/reload/grape_api.rb