reflexive 0.0.6 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,6 +10,10 @@ shared_examples_for "fresh Rails app with Reflexive installed" do
10
10
  get("/").should include("Welcome aboard")
11
11
  end
12
12
 
13
+ it "doesn't respond on not existing path" do
14
+ proc { get("/not_exist") }.should raise_error
15
+ end
16
+
13
17
  it "responds for Reflexive paths" do
14
18
  constant_reflexion = get("/reflexive/constants/ActiveRecord::Base")
15
19
  constant_reflexion.should include("ActiveRecord")
@@ -112,11 +116,14 @@ describe "Integration with" do
112
116
  class Application < Rails::Application
113
117
  config.middleware.insert_after("Rack::Lock", "Reflexive::Application")
114
118
  RUBY
119
+
120
+ patch_app_file("Gemfile", /\z/, "\ngem 'reflexive'")
115
121
  end
116
122
 
117
123
  it "properly" do
118
124
  Dir.chdir($app_dir) do
119
125
  IO.read("config/application.rb").should include("Reflexive")
126
+ IO.read("Gemfile").should include("reflexive")
120
127
  end
121
128
  end
122
129
 
@@ -69,25 +69,35 @@ def build_and_install_test_gem
69
69
  end
70
70
  end
71
71
 
72
+ SERVER_STARTUP_TIME = 20
72
73
  def spawn_server_and_wait_for_response(cmd)
73
74
  $server_pid = spawn(tmp_gemset_env, cmd)
74
- puts "Spawned server with #{ $server_pid } PID"
75
- tries = 0
76
- print "Waiting for server to start..."
77
- started = false
78
- while (tries += 1) < 10 && !started
79
- started = get("/").include?("Welcome aboard") rescue false
80
- print "."
81
- sleep 1
75
+ begin
76
+ trap("CLD") { raise "Failed to start server: server died prematurely" }
77
+ puts "Spawned server with #{ $server_pid } PID"
78
+ tries = 0
79
+ print "Waiting for server to start..."
80
+ started = false
81
+ while (tries += 1) < SERVER_STARTUP_TIME && !started
82
+ started = get("/").include?("Welcome aboard") rescue false
83
+ print "."
84
+ sleep 1
85
+ end
86
+ print "\n"
87
+ unless started
88
+ raise "Failed to start server: server didn't respond in #{ SERVER_STARTUP_TIME } seconds"
89
+ end
90
+ rescue Exception => e
91
+ raise e.exception("Failed to start server: #{ e.message }")
92
+ ensure
93
+ trap("CLD", nil)
82
94
  end
83
- print "\n"
84
- abort "Failed to start server" unless started
85
95
  end
86
96
 
87
97
  def terminate_server_blocking
88
98
  puts "Terminating server with #{ $server_pid } PID..."
89
99
  `kill -9 #{ $server_pid }`
90
- Process::waitpid2($server_pid)
100
+ Process::waitpid2($server_pid) rescue nil
91
101
  end
92
102
 
93
103
  def get(path)
@@ -57,7 +57,7 @@ describe Reflexive::ReflexiveRipper do
57
57
  describe "injects method call scanner event tags" do
58
58
  specify "m!" do
59
59
  scanner_events_for("m!").should(have_tags(
60
- {:method_call=>{:name=>"m!", :receiver=>[], :scope => []}}
60
+ {:method_call=>{:name=>"m!", :receiver=>:class, :scope => []}}
61
61
  ))
62
62
  end
63
63
 
@@ -109,7 +109,7 @@ describe Reflexive::ReflexiveRipper do
109
109
  specify "1.tap { (dv = 1).tap { puts dv } }" do
110
110
  scanner_events_for("1.tap { (dv = 1).tap { puts dv } }").should(have_exact_tags(
111
111
  {:local_variable_assignment=>"2:dv"},
112
- {:method_call=>{:name=>"puts", :receiver=>[], :scope => []}},
112
+ {:method_call=>{:name=>"puts", :receiver=>:class, :scope => []}},
113
113
  {:local_variable_access=>"2:dv"}
114
114
  ))
115
115
  end
@@ -123,8 +123,9 @@ describe Reflexive::ReflexiveRipper do
123
123
  specify "tv = 1; def m; puts tv; end" do
124
124
  scanner_events_for("tv = 1; def m; puts tv; end").should(have_tags(
125
125
  {:local_variable_assignment=>"1:tv"},
126
- {:method_call=>{:name=>"puts", :receiver=>[:instance], :scope => []}},
127
- {:method_call=>{:name=>"tv", :receiver=>[:instance], :scope => []}}))
126
+ {:method_call=>{:name=>"puts", :receiver=>:instance, :scope => []}},
127
+ {:method_call=>{:name=>"tv", :receiver=>:instance, :scope => []}}
128
+ ))
128
129
  end
129
130
 
130
131
  end
@@ -133,44 +134,54 @@ describe Reflexive::ReflexiveRipper do
133
134
  describe "for method calls" do
134
135
  specify "from top level" do
135
136
  scanner_events_for("m()").should(have_tags(
136
- {:method_call=>{:name=>"m", :receiver=>[], :scope => []}}))
137
+ {:method_call=>{:name=>"m", :receiver=>:class, :scope => []}}
138
+ ))
137
139
  end
138
140
 
139
141
  specify "class definition level" do
140
142
  scanner_events_for("class C; cm(); end").should(have_tags(
141
- {:method_call=>{:name=>"cm", :receiver=>["C"], :scope => ["C"]}}))
143
+ {:method_call=>{:name=>"cm", :receiver=>:class, :scope => ["C"]}}
144
+ ))
142
145
  scanner_events_for("module M; cm(); end").should(have_tags(
143
- {:method_call=>{:name=>"cm", :receiver=>["M"], :scope => ["M"]}}))
146
+ {:method_call=>{:name=>"cm", :receiver=>:class, :scope => ["M"]}}
147
+ ))
144
148
  end
145
149
 
146
150
  specify "class instance level" do
147
151
  scanner_events_for("class C; def im1; im2; end end").should(have_tags(
148
- {:method_call=>{:name=>"im2", :receiver=>["C", :instance], :scope => ["C"]}}))
152
+ {:method_call=>{:name=>"im2", :receiver=>:instance, :scope => ["C"]}}
153
+ ))
149
154
  scanner_events_for("module M; def im1; im2; end end").should(have_tags(
150
- {:method_call=>{:name=>"im2", :receiver=>["M", :instance], :scope => ["M"]}}))
155
+ {:method_call=>{:name=>"im2", :receiver=>:instance, :scope => ["M"]}}
156
+ ))
151
157
  end
152
158
 
153
159
  specify "class singleton level" do
154
160
  scanner_events_for("class C; def self.cm1() cm2; end end").should(have_tags(
155
- {:method_call=>{:name=>"cm2", :receiver=>["C"], :scope => ["C"]}}))
161
+ {:method_call=>{:name=>"cm2", :receiver=>:class, :scope => ["C"]}}
162
+ ))
156
163
  scanner_events_for("module M; def self.cm1() cm2; end end").should(have_tags(
157
- {:method_call=>{:name=>"cm2", :receiver=>["M"], :scope => ["M"]}}))
164
+ {:method_call=>{:name=>"cm2", :receiver=>:class, :scope => ["M"]}}
165
+ ))
166
+ end
167
+
168
+ specify "class singleton level for methods defined with class << self" do
169
+ scanner_events_for("class C; class << self; def cm1(); cm2; end end end").should(have_tags(
170
+ {:method_call=>{:name=>"cm2", :receiver=>:class, :scope => ["C"]}}
171
+ ))
158
172
  end
159
173
 
160
- pending "nested method calls with constant references" do
174
+ specify "nested method calls with constant references" do
161
175
  src = <<-RUBY
162
176
  module M
163
177
  class C
164
- def self.m
165
- end
166
- end
167
- end
168
- class M::C
169
- def m
170
- c = C.m
171
178
  end
179
+ C.new
172
180
  end
173
181
  RUBY
182
+ scanner_events_for(src).should(have_tags(
183
+ {:method_call=>{:name=>"new", :receiver=>["C"], :scope => ["M"]}}
184
+ ))
174
185
  end
175
186
  end
176
187
 
@@ -233,6 +244,33 @@ describe Reflexive::ReflexiveRipper do
233
244
  ))
234
245
 
235
246
  end
247
+
248
+ specify "from instance methods params" do
249
+ scanner_events_for("def m(a = C.new(m1), b = D.new(m2)); end").should(have_tags(
250
+ {:constant_access=>{:name=>"C", :scope=>[]}},
251
+ {:constant_access=>{:name=>"D", :scope=>[]}}
252
+ ))
253
+ end
254
+
255
+ specify "for superclass" do
256
+ scanner_events_for("class C < D; end").should(have_tags(
257
+ {:constant_access=>{:name=>"D", :scope=>[]}}
258
+ ))
259
+ end
260
+
261
+ specify "autoload hint" do
262
+ scanner_events_for("module M; autoload :C; end").should(have_tags(
263
+ {:constant_access=>{:name=>"C", :scope=>["M"]}}
264
+ ))
265
+
266
+ scanner_events_for("module M; autoload 'C'; end").should(have_tags(
267
+ {:constant_access=>{:name=>"C", :scope=>["M"]}}
268
+ ))
269
+
270
+ scanner_events_for("module M; autoload('C'); end").should(have_tags(
271
+ {:constant_access=>{:name=>"C", :scope=>["M"]}}
272
+ ))
273
+ end
236
274
  end
237
275
  end
238
276
 
@@ -26,6 +26,13 @@ end
26
26
 
27
27
  C2.extend(M2)
28
28
 
29
+ module ModuleDescendantBaseModule
30
+ end
31
+
32
+ module ModuleDescendantModule
33
+ include ModuleDescendantBaseModule
34
+ end
35
+
29
36
  describe "Reflexive.loaded_features_lookup" do
30
37
  before(:all) do
31
38
  @native_feature = $LOADED_FEATURES.detect { |f| f =~ /\.so\z/ }
@@ -61,6 +68,10 @@ describe "Reflexive.constant_lookup" do
61
68
  Reflexive.constant_lookup("::String", "Some::Ignored::Scope").should == ::String
62
69
  end
63
70
 
71
+ it "looks up top-level constants when passed empty scope" do
72
+ Reflexive.constant_lookup("String", "").should == ::String
73
+ end
74
+
64
75
  it "returns nil for non existing top-level constant" do
65
76
  Reflexive.constant_lookup("::StringAsd", "Some::Ignored::Scope").should == nil
66
77
  end
@@ -96,4 +107,8 @@ describe "Reflexive.descendants" do
96
107
  it "finds singleton class descendant" do
97
108
  Reflexive.descendants(M2).should =~ [C2]
98
109
  end
110
+
111
+ it "reports modules which include module as descendants" do
112
+ Reflexive.descendants(ModuleDescendantBaseModule) =~ [ModuleDescendantModule]
113
+ end
99
114
  end
@@ -19,9 +19,26 @@
19
19
  <% unless @methods.files.empty? %>
20
20
  <div>
21
21
  <h4>Defined In Files</h4>
22
- <% @methods.files.sort.each do |path| %>
22
+
23
+ <% files = @methods.files.sort %>
24
+ <% shown, hidden = files[0..5], files[6..-1] %>
25
+
26
+ <% shown.each do |path| %>
23
27
  <%= link_to_file(path) %><br/>
24
28
  <% end %>
29
+
30
+ <% if hidden && !hidden.empty? %>
31
+ <div class="opener">
32
+ <a class="trigger" href="#">
33
+ ... <%= hidden.size %> files more
34
+ </a>
35
+ <div class="content">
36
+ <% hidden.each do |path| %>
37
+ <%= link_to_file(path) %><br/>
38
+ <% end %>
39
+ </div>
40
+ </div>
41
+ <% end %>
25
42
  </div>
26
43
  <% end %>
27
44
 
data/views/dashboard.erb CHANGED
@@ -1,10 +1,9 @@
1
- <h1>
2
- Reflexive </h1>
1
+ <h1> Reflexive </h1>
3
2
 
4
3
  <div class="dashboard">
5
4
  <% if defined?(ActiveRecord::Base) || defined?(ApplicationController) %>
6
5
  <div class="row">
7
- <div class="column">
6
+ <div class="column first">
8
7
  <% if defined?(::ActiveRecord::Base) %>
9
8
  <h2>Models</h2>
10
9
 
@@ -27,7 +26,7 @@
27
26
  </div>
28
27
  <% end %>
29
28
  <div class="row">
30
- <div class="column">
29
+ <div class="column first">
31
30
  <h2>Favorites</h2>
32
31
  <% favorites = filter_existing_constants(%w(Rails ActiveSupport ActiveResource
33
32
  ActiveRecord ActionView ActionController ActionDispatch ActionMailer ActiveModel
data/views/layout.erb CHANGED
@@ -10,6 +10,16 @@
10
10
  </head>
11
11
  <body>
12
12
 
13
+ <% if Reflexive.class_reloading_active? %>
14
+ <div style="background-color: #ffc0cb; border: 1px solid gray; padding: 1em 1em; width: 500px">
15
+ Warning! You're running Reflexive with <code>config.cache_classes = false</code> <br/>
16
+ Rails setting (which is the default for running server in development environment).<br/>
17
+ Currently Reflexive isn't compatible with this setting and you may want to<br/>
18
+ either set <code>config.cache_classes = true</code> in your environment configuration<br/>
19
+ file or run the server in production mode with <br/><code>rails s --environment=production</code>
20
+ </div>
21
+ <% end %>
22
+
13
23
  <div class="dashboard-link">
14
24
  <%= link_to("Reflexive Dashboard", dashboard_path) unless request.path == dashboard_path %>
15
25
  </div>
@@ -1,9 +1,17 @@
1
1
  <h2>
2
2
  <%= @klass.name %>#<%= @method_name %>
3
3
  </h2>
4
+
5
+ <div>
6
+ Documentation provided by <a href="http://apidock.com/">APIdock</a>
7
+ <%= link_to apidock_path(@klass.name, @level, @method_name),
8
+ apidock_path(@klass.name, @level, @method_name) %> :
9
+
10
+ </div>
11
+
4
12
  <%= content_tag :iframe,
5
13
  "",
6
- :src => apidock_path(@klass.name, @method_name),
14
+ :src => apidock_path(@klass.name, @level, @method_name),
7
15
  :frameborder => 0,
8
16
  :style => "width: 960px; height: 100%; position: absolute",
9
17
  :id => "apidock" %>
@@ -0,0 +1,19 @@
1
+ <div>
2
+ Calling <code><%= @name %></code> <%= @level %> method from
3
+ <code><%= @klass %></code> can dispatch to following methods
4
+ </div>
5
+
6
+ <% if @last_resort_lookup_used %>
7
+ <div>
8
+ Note: the list of methods below was generated using last resort lookup
9
+ algorithm, i.e. by just looking for named method in any class/module
10
+ currently loaded.
11
+ </div>
12
+ <% end %>
13
+
14
+ <div>
15
+ <% links = @definitions.
16
+ sort_by { |klass, _, _| klass.to_s }.
17
+ map { |d| full_name_link_to_method(*d) } %>
18
+ <%= content_tag :pre, links.join("\n") %>
19
+ </div>
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reflexive
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
7
+ - 1
8
8
  - 0
9
- - 6
10
- version: 0.0.6
9
+ version: 0.1.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - Evgeniy Dolzhenko
@@ -15,7 +14,7 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2010-05-17 00:00:00 -07:00
17
+ date: 2010-05-20 00:00:00 -07:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
@@ -24,12 +23,13 @@ dependencies:
24
23
  requirement: &id001 !ruby/object:Gem::Requirement
25
24
  none: false
26
25
  requirements:
27
- - - ">="
26
+ - - "="
28
27
  - !ruby/object:Gem::Version
29
- hash: 3
30
28
  segments:
29
+ - 1
30
+ - 1
31
31
  - 0
32
- version: "0"
32
+ version: 1.1.0
33
33
  type: :runtime
34
34
  version_requirements: *id001
35
35
  - !ruby/object:Gem::Dependency
@@ -38,12 +38,12 @@ dependencies:
38
38
  requirement: &id002 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
- - - ">="
41
+ - - "="
42
42
  - !ruby/object:Gem::Version
43
- hash: 3
44
43
  segments:
44
+ - 1
45
45
  - 0
46
- version: "0"
46
+ version: "1.0"
47
47
  type: :runtime
48
48
  version_requirements: *id002
49
49
  - !ruby/object:Gem::Dependency
@@ -52,12 +52,13 @@ dependencies:
52
52
  requirement: &id003 !ruby/object:Gem::Requirement
53
53
  none: false
54
54
  requirements:
55
- - - ">="
55
+ - - "="
56
56
  - !ruby/object:Gem::Version
57
- hash: 3
58
57
  segments:
59
58
  - 0
60
- version: "0"
59
+ - 3
60
+ - 40
61
+ version: 0.3.40
61
62
  type: :runtime
62
63
  version_requirements: *id003
63
64
  - !ruby/object:Gem::Dependency
@@ -66,77 +67,108 @@ dependencies:
66
67
  requirement: &id004 !ruby/object:Gem::Requirement
67
68
  none: false
68
69
  requirements:
69
- - - ">="
70
+ - - "="
70
71
  - !ruby/object:Gem::Version
71
- hash: 3
72
72
  segments:
73
73
  - 0
74
- version: "0"
74
+ - 9
75
+ - 3
76
+ version: 0.9.3
75
77
  type: :runtime
76
78
  version_requirements: *id004
77
79
  - !ruby/object:Gem::Dependency
78
- name: rdiscount
80
+ name: rails
79
81
  prerelease: false
80
82
  requirement: &id005 !ruby/object:Gem::Requirement
81
83
  none: false
82
84
  requirements:
83
- - - ">="
85
+ - - "="
84
86
  - !ruby/object:Gem::Version
85
- hash: 3
86
87
  segments:
88
+ - 3
87
89
  - 0
88
- version: "0"
89
- type: :runtime
90
+ - 0
91
+ - beta3
92
+ version: 3.0.0.beta3
93
+ type: :development
90
94
  version_requirements: *id005
91
95
  - !ruby/object:Gem::Dependency
92
- name: rails
96
+ name: rspec
93
97
  prerelease: false
94
98
  requirement: &id006 !ruby/object:Gem::Requirement
95
99
  none: false
96
100
  requirements:
97
101
  - - "="
98
102
  - !ruby/object:Gem::Version
99
- hash: -690468206
100
103
  segments:
101
- - 3
104
+ - 2
102
105
  - 0
103
106
  - 0
104
- - beta3
105
- version: 3.0.0.beta3
107
+ - beta
108
+ - 8
109
+ version: 2.0.0.beta.8
106
110
  type: :development
107
111
  version_requirements: *id006
108
112
  - !ruby/object:Gem::Dependency
109
- name: rspec
113
+ name: sinatra-reloader
110
114
  prerelease: false
111
115
  requirement: &id007 !ruby/object:Gem::Requirement
112
116
  none: false
113
117
  requirements:
114
118
  - - "="
115
119
  - !ruby/object:Gem::Version
116
- hash: -44051750
117
120
  segments:
118
- - 2
119
- - 0
120
121
  - 0
121
- - beta
122
- - 8
123
- version: 2.0.0.beta.8
122
+ - 4
123
+ - 1
124
+ version: 0.4.1
124
125
  type: :development
125
126
  version_requirements: *id007
126
127
  - !ruby/object:Gem::Dependency
127
- name: sinatra-reloader
128
+ name: thin
128
129
  prerelease: false
129
130
  requirement: &id008 !ruby/object:Gem::Requirement
130
131
  none: false
131
132
  requirements:
132
- - - ">="
133
+ - - "="
133
134
  - !ruby/object:Gem::Version
134
- hash: 3
135
135
  segments:
136
- - 0
137
- version: "0"
136
+ - 1
137
+ - 2
138
+ - 7
139
+ version: 1.2.7
138
140
  type: :development
139
141
  version_requirements: *id008
142
+ - !ruby/object:Gem::Dependency
143
+ name: rack-test
144
+ prerelease: false
145
+ requirement: &id009 !ruby/object:Gem::Requirement
146
+ none: false
147
+ requirements:
148
+ - - "="
149
+ - !ruby/object:Gem::Version
150
+ segments:
151
+ - 0
152
+ - 5
153
+ - 3
154
+ version: 0.5.3
155
+ type: :development
156
+ version_requirements: *id009
157
+ - !ruby/object:Gem::Dependency
158
+ name: webrat
159
+ prerelease: false
160
+ requirement: &id010 !ruby/object:Gem::Requirement
161
+ none: false
162
+ requirements:
163
+ - - "="
164
+ - !ruby/object:Gem::Version
165
+ segments:
166
+ - 0
167
+ - 7
168
+ - 1
169
+ version: 0.7.1
170
+ type: :development
171
+ version_requirements: *id010
140
172
  description:
141
173
  email:
142
174
  - dolzenko@gmail.com
@@ -153,10 +185,12 @@ files:
153
185
  - lib/reflexive/columnizer.rb
154
186
  - lib/reflexive/constantize.rb
155
187
  - lib/reflexive/core_ext/kernel/singleton_class.rb
188
+ - lib/reflexive/core_ext/module/reflexive_instance_methods.rb
156
189
  - lib/reflexive/descendants.rb
157
190
  - lib/reflexive/faster_open_struct.rb
158
191
  - lib/reflexive/helpers.rb
159
192
  - lib/reflexive/methods.rb
193
+ - lib/reflexive/method_lookup.rb
160
194
  - lib/reflexive/parse_tree_top_down_walker.rb
161
195
  - lib/reflexive/reflexive_ripper.rb
162
196
  - lib/reflexive/routing_helpers.rb
@@ -174,12 +208,16 @@ files:
174
208
  - views/files_show.erb
175
209
  - views/layout.erb
176
210
  - views/methods_apidock.erb
211
+ - views/methods_choose.erb
177
212
  - views/methods_definition.erb
178
213
  - views/methods_rubydoc.erb
179
214
  - spec/coderay_html_encoder_spec.rb
180
215
  - spec/coderay_ruby_scanner_spec.rb
216
+ - spec/integration_spec.rb
217
+ - spec/integration_spec_fixture.rb
181
218
  - spec/io_interceptor.rb
182
219
  - spec/methods_spec.rb
220
+ - spec/method_lookup_spec.rb
183
221
  - spec/rails_integration_spec.rb
184
222
  - spec/rails_integration_spec_helper.rb
185
223
  - spec/reflexive_ripper_spec.rb
@@ -206,7 +244,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
206
244
  requirements:
207
245
  - - ">="
208
246
  - !ruby/object:Gem::Version
209
- hash: 49
210
247
  segments:
211
248
  - 1
212
249
  - 9
@@ -217,7 +254,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
217
254
  requirements:
218
255
  - - ">="
219
256
  - !ruby/object:Gem::Version
220
- hash: 3
221
257
  segments:
222
258
  - 0
223
259
  version: "0"