grape-reload 0.0.2 → 0.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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