rails-caddy 0.0.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (32) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +69 -0
  3. data/VERSION.yml +4 -0
  4. data/lib/rails-caddy.rb +43 -0
  5. data/lib/rails-caddy/controllers/rails_caddy_controller.rb +17 -0
  6. data/lib/rails-caddy/controllers/sanitize_email_controller.rb +42 -0
  7. data/lib/rails-caddy/controllers/session_editing_controller.rb +21 -0
  8. data/lib/rails-caddy/controllers/timecop_controller.rb +56 -0
  9. data/lib/rails-caddy/errors.rb +8 -0
  10. data/lib/rails-caddy/helpers/rails_caddy_helper.rb +33 -0
  11. data/lib/rails-caddy/session_controller_finder.rb +17 -0
  12. data/lib/rails-caddy/views/_rails_caddy.html.erb +57 -0
  13. data/lib/rails-caddy/views/_rails_caddy_css.html.erb +60 -0
  14. data/lib/rails-caddy/views/_rails_caddy_js.html.erb +88 -0
  15. data/test/README.txt +40 -0
  16. data/test/files/acet.rb +40 -0
  17. data/test/files/fct.rb +35 -0
  18. data/test/files/rcct.rb +13 -0
  19. data/test/files/sanitize_email_action_controller_extensions_test_methods.rb +71 -0
  20. data/test/files/sanitize_email_controller_test_methods.rb +31 -0
  21. data/test/files/session_editing_controller_test_methods.rb +41 -0
  22. data/test/files/timecop_action_controller_extensions_test_methods.rb +55 -0
  23. data/test/files/timecop_controller_test_methods.rb +30 -0
  24. data/test/geminstaller.yml +5 -0
  25. data/test/rails_caddy_controller_test.rb +43 -0
  26. data/test/rails_caddy_helper_test.rb +24 -0
  27. data/test/rails_caddy_test.rb +39 -0
  28. data/test/rails_modifier.rb +131 -0
  29. data/test/routes.rb +3 -0
  30. data/test/session_controller_finder_test.rb +57 -0
  31. data/test/test_helper.rb +12 -0
  32. metadata +110 -0
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 John Trupiano
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,69 @@
1
+ = rails-caddy
2
+
3
+ A developer's QA "caddy" that aids in QA'ing, debugging, and otherwise navigating your application during development and/or QA.
4
+
5
+ == Rails Compatibility
6
+
7
+ Tests cover rails 2.1.2, 2.2.2, and 2.3.2 specifically. Previous releases on each minor version have not been explicitly tested, but I suspect they should all function equally well.
8
+
9
+ == Usage
10
+
11
+ RULE #1: DO NOT DEPLOY THIS TO PRODUCTION. I WILL HAVE NO EMPATHY WHATSOEVER IF YOU DO NOT HEED MY WARNING. THIS IS A VERY DANGEROUS GEM THAT WILL DEFINITELY SCREW YOU OVER IF YOU DEPLOY IT TO PRODUCTION.
12
+
13
+ This process is not currently scripted, but following these steps will get you off and running.
14
+
15
+ * edit application.rb
16
+
17
+ if Object.const_defined?(:RailsCaddy)
18
+ helper RailsCaddyHelper
19
+ around_filter :handle_sanitize_email
20
+ around_filter :handle_timecop_offset, :except => [:timecop_update, :timecop_reset]
21
+ end
22
+
23
+ * edit config/environments/development.rb -- DO NOT MAKE THIS AVAILABLE TO PRODUCTION!!!
24
+
25
+ config.gem "rails-caddy"
26
+
27
+ config.after_initialize do
28
+ require 'rails-caddy'
29
+ require_dependency 'application_controller' # 'application' if pre rails 2.3
30
+ RailsCaddy.init!
31
+
32
+ ActionMailer::Base.sanitized_recipients = "nobody@smartlogicsolutions.com"
33
+ end
34
+
35
+ * add just before you close your body tag in your layout (it's actually unimportant where you place it, as long as it's in the body):
36
+
37
+ <%= rails_caddy if Object.const_defined?(:RailsCaddy) %>
38
+
39
+ * add to the top of config/routes.rb
40
+
41
+ RailsCaddy.define_routes!(map) if Object.const_defined?(:RailsCaddy)
42
+
43
+ == Dependencies
44
+
45
+ rails-caddy is dependent on the {sanitize_email gem}[http://github.com/jtrupiano/sanitize_email/tree/master]. Unfortunately, for the time being you'll need to build and install that locally. Why? Because the dependency is on +sanitize_email+ and NOT <tt>jtrupiano-sanitize_email</tt>, the latter of which can be installed remotely. Hopefully this will change soon (that's _your_ cue to fork and fix).
46
+
47
+ == Building/Testing
48
+
49
+ In order to run the tests, you'll want to build the gem. Why? Because <tt>rake test:rails_compatibility</tt> tests all supported versions of rails (see <b>Rails Compatibility</b>, above). It does this by creating mini-Rails apps for each version and config-gem'ing rails-caddy (<tt>config.gem 'rails-caddy'</tt>). If you don't build the gem and try to run the tests, you'll get an error telling you to <tt>run `rake gems:install`</tt>.
50
+
51
+ The easiest way to build the gem is to install {technicalpickle's}[http://technicalpickles.com/] {jeweler gem}[http://github.com/technicalpickles/jeweler/tree/master]: <tt>sudo gem install jeweler</tt>.
52
+
53
+ After jeweler is installed, you can build and install with some handy rake tasks:
54
+
55
+ rake build
56
+ rake install
57
+
58
+ <b>n.b.</b> <tt>rake install</tt> uses +sudo+
59
+
60
+ (Problems? See *Dependencies*, above.)
61
+
62
+ Now you can run your tests:
63
+
64
+ rake test:all # Run all test suites.
65
+ rake test:rails_compatibility # Test all supported versions of rails.
66
+
67
+ == Copyright
68
+
69
+ Copyright (c) 2009 John Trupiano. See LICENSE for details.
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 0
3
+ :minor: 0
4
+ :patch: 8
@@ -0,0 +1,43 @@
1
+ require 'timecop'
2
+ require 'actionmailer' # would like to remove this
3
+ require 'sanitize_email'
4
+ require 'rails-caddy/errors'
5
+ require 'rails-caddy/controllers/session_editing_controller'
6
+ require 'rails-caddy/controllers/timecop_controller'
7
+ require 'rails-caddy/controllers/sanitize_email_controller'
8
+ require 'rails-caddy/helpers/rails_caddy_helper'
9
+
10
+ $rails_caddy_activated = false
11
+
12
+ class RailsCaddy
13
+
14
+ def self.init!
15
+ # extend ActionController::Base
16
+ ActionController::Base.send(:include, TimecopController::ActionControllerExtensions)
17
+ ActionController::Base.send(:include, SanitizeEmailController::ActionControllerExtensions)
18
+
19
+ # Pull in the RailsCaddyController
20
+ require 'rails-caddy/controllers/rails_caddy_controller'
21
+
22
+ # Lastly, let's add our views to the load path...
23
+ ActionController::Base.append_view_path(File.expand_path(File.join(File.dirname(__FILE__), "rails-caddy", "views")))
24
+
25
+ # we will inspect this at a few places in the consuming rails app, most notably config/routes.rb
26
+ $rails_caddy_activated = true
27
+ end
28
+
29
+ def self.define_routes!(map)
30
+ # Session editing routes
31
+ map.update_session '/rails_caddy/update_session/:id', :controller => 'rails_caddy', :action => 'update_session'
32
+ map.remove_session '/rails_caddy/remove_session/:id', :controller => 'rails_caddy', :action => 'remove_session'
33
+
34
+ # Timecop routes
35
+ map.timecop_update '/rails_caddy/timecop_update', :controller => 'rails_caddy', :action => 'timecop_update'
36
+ map.timecop_reset '/rails_caddy/timecop_reset', :controller => 'rails_caddy', :action => 'timecop_reset'
37
+
38
+ # Sanitize Email routes
39
+ map.set_sanitize_email_address '/rails_caddy/set_sanitize_email_address', :controller => 'rails_caddy', :action => 'set_sanitize_email_address'
40
+ map.unset_sanitize_email_address '/rails_caddy/unset_sanitize_email_address', :controller => 'rails_caddy', :action => 'unset_sanitize_email_address'
41
+ end
42
+
43
+ end
@@ -0,0 +1,17 @@
1
+ require 'rails-caddy/session_controller_finder'
2
+
3
+ # Find the controller responsible for establishing session
4
+ session_controller = SessionControllerFinder.find
5
+
6
+ # Dynamically define the RailsCaddyController now
7
+ c = Class.new(session_controller) do
8
+ include SessionEditingController
9
+ include TimecopController
10
+ include SanitizeEmailController
11
+
12
+ def verify_authenticity_token
13
+ # this is lame that I have to override it here...can't figure out why a skip_before_filter fails
14
+ end
15
+
16
+ end
17
+ Object.const_set("RailsCaddyController", c)
@@ -0,0 +1,42 @@
1
+ module SanitizeEmailController
2
+
3
+ def self.included(base)
4
+ base.send(:include, Actions)
5
+ end
6
+
7
+ module Actions
8
+
9
+ def set_sanitize_email_address
10
+ session[:sanitize_email_address] = params[:value]
11
+ render :status => 200, :text => params[:value]
12
+ end
13
+
14
+ def unset_sanitize_email_address
15
+ session[:sanitize_email_address] = nil
16
+ render :status => 200, :text => "nil"
17
+ end
18
+ end
19
+
20
+ module ActionControllerExtensions
21
+ # def self.included(base)
22
+ # base.class_eval do
23
+ # around_filter :handle_sanitize_email
24
+ # end
25
+ # end
26
+
27
+ def handle_sanitize_email
28
+ if session[:sanitize_email_address].nil?
29
+ yield
30
+ return
31
+ end
32
+
33
+ @original_sanitized_recipients = ActionMailer::Base.sanitized_recipients
34
+ ActionMailer::Base.sanitized_recipients = session[:sanitize_email_address]
35
+ yield
36
+ ensure
37
+ ActionMailer::Base.sanitized_recipients = @original_sanitized_recipients
38
+ end
39
+
40
+ private :handle_sanitize_email
41
+ end
42
+ end
@@ -0,0 +1,21 @@
1
+ module SessionEditingController
2
+
3
+ def update_session
4
+ if params[:id].nil?
5
+ render :status => 422, :text => "Invalid request. No session variable provided."
6
+ return false
7
+ end
8
+ session[params[:id].to_sym] = params[:value]
9
+ render :status => 200, :text => params[:value]
10
+ end
11
+
12
+ def remove_session
13
+ if params[:id].nil?
14
+ render :status => 422, :text => "Invalid request. Session variable is either missing or invalid."
15
+ return false
16
+ end
17
+ session[params[:id].to_sym] = nil
18
+ render :status => 200, :nothing => true
19
+ end
20
+
21
+ end
@@ -0,0 +1,56 @@
1
+ module TimecopController
2
+
3
+ def self.included(base)
4
+ # base.class_eval do
5
+ # # Make sure we don't reset our own time!
6
+ # skip_filter :handle_timecop_offset
7
+ # end
8
+ base.send(:include, Actions)
9
+ end
10
+
11
+ module Actions
12
+ def timecop_update
13
+ year, month, day, hour, min, sec = params[:year], params[:month], params[:day], params[:hour], params[:min], params[:sec]
14
+ session[:timecop_adjusted_time] = Time.local(year, month, day, hour, min, sec)
15
+ render :status => 200, :nothing => true
16
+ end
17
+
18
+ def timecop_reset
19
+ session[:timecop_adjusted_time] = nil
20
+ render :status => 200, :nothing => true
21
+ end
22
+ end
23
+
24
+ module ActionControllerExtensions
25
+ # def self.included(base)
26
+ # base.class_eval do
27
+ # around_filter :handle_timecop_offset
28
+ # end
29
+ # end
30
+
31
+ # to be used as an around_filter
32
+ def handle_timecop_offset
33
+ # Establish now
34
+ if !session[:timecop_adjusted_time].nil?
35
+ #puts "***** Time traveling to #{session[:timecop_adjusted_time].to_s}"
36
+ Timecop.travel(session[:timecop_adjusted_time])
37
+ else
38
+ Timecop.return
39
+ end
40
+
41
+ # Run the intended action
42
+ yield
43
+
44
+ # we want to continue to slide time forward, even if it's only 3 seconds at a time.
45
+ # this ensures that subsequent calls during the same "time travel" actually pass time
46
+ if !session[:timecop_adjusted_time].nil?
47
+ #puts "====== Resetting session to: #{Time.now + 3}"
48
+ session[:timecop_adjusted_time] = Time.now + 3 # slide it forward a couple of seconds
49
+ end
50
+ end
51
+
52
+ private :handle_timecop_offset
53
+
54
+ end
55
+
56
+ end
@@ -0,0 +1,8 @@
1
+ class RailsCaddy
2
+
3
+ class SessionUninitializedError < StandardError
4
+ end
5
+
6
+ class SessionControllerNotFoundError < StandardError
7
+ end
8
+ end
@@ -0,0 +1,33 @@
1
+ module RailsCaddyHelper
2
+ # actually embeds the magic that is the Rails Caddy
3
+ def rails_caddy
4
+ render(:partial => '/rails_caddy')
5
+ end
6
+
7
+ def translated_remove_session_path
8
+ url = remove_session_path
9
+ url << "/" unless url.match(/\/$/)
10
+ end
11
+
12
+ def rc_in_place_editor(key, field_id, url)
13
+ function = "RailsCaddy.editors['" + key + "'] = new Ajax.InPlaceEditor("
14
+ function << "'#{field_id}', "
15
+ function << "'#{url}'"
16
+ function << ');'
17
+
18
+ javascript_tag(function)
19
+ end
20
+
21
+ def rc_in_place_editor_field(key, value)
22
+ tag = ::ActionView::Helpers::InstanceTag.new("rails_caddy", key, self)
23
+ tag_options = {:tag => "span", :id => "rails_caddy_#{key}_in_place_editor", :name => "value", :class => "in_place_editor_field"}
24
+
25
+ # rails < 2.3 needs to be treated with kid gloves.
26
+ url = update_session_path
27
+ url << "/" unless url.match(/\/$/)
28
+ url << key
29
+
30
+ tag.content_tag(tag_options.delete(:tag), value, tag_options) + rc_in_place_editor(key, tag_options[:id], url)
31
+ end
32
+
33
+ end
@@ -0,0 +1,17 @@
1
+ # Responsible for locating the controller responsible for establishing the session
2
+ class SessionControllerFinder
3
+ def self.find
4
+ if !Object.const_defined?(:ApplicationController)
5
+ raise RailsCaddy::SessionControllerNotFoundError,
6
+ "Cannot find ApplicationController. If you're sure that you have defined it, try adding require_dependency 'application_controller' prior to invoking RailsCaddy.init!"
7
+ end
8
+
9
+ candidate = ApplicationController
10
+ # if candidate.session_options[:key].nil?
11
+ # raise RailsCaddy::SessionUninitializedError,
12
+ # "session does not appear to be established for #{candidate.class}. session: #{candidate.session_options.inspect}"
13
+ # end
14
+
15
+ candidate
16
+ end
17
+ end
@@ -0,0 +1,57 @@
1
+ <%= render(:partial => '/rails_caddy_css') %>
2
+
3
+ <%= render(:partial => '/rails_caddy_js')%>
4
+
5
+ <div id="railsCaddy">
6
+
7
+ <a href="#" id="railsCaddyTab">caddy</a>
8
+
9
+ <div id="railsCaddyContents" style="display: none;">
10
+ <div id="railsCaddyContentsInner">
11
+ <div id="railsCaddySession">
12
+ <h2>Session</h2>
13
+ <div id="sessionObjects">
14
+ <script type="text/javascript">
15
+ <% (session.data.keys - ["flash", :timecop_adjusted_time, :sanitize_email_address]).each do |key| -%>
16
+ <% next if session[key].nil? -%>
17
+ document.write(RailsCaddy.sessionVariableEditor("<%= escape_javascript(key.to_s) %>", "<%= escape_javascript(session[key].to_s) %>"));
18
+ <% end -%>
19
+ </script>
20
+ </div>
21
+ <p><a href="javascript:void(0)" onclick="RailsCaddy.addSessionVariable();">+ New Session Variable</a></p>
22
+ </div>
23
+
24
+ <div id="railsCaddyTimecop">
25
+ <h2>Timecop</h2>
26
+ <p>The time is <strong style="color: red;"><%= Time.now.to_s(:db) %></strong></p>
27
+ <% form_remote_tag :url => timecop_update_path do -%>
28
+ <% %w(year month day hour min sec).each do |field| -%>
29
+ <%= text_field_tag field, Time.now.send(field), :size => (field == "year" ? 3 : 1) %>
30
+ <% end -%>
31
+ <p>
32
+ <%= submit_tag "Time Travel" %>
33
+ <%= link_to_remote "Reset", :url => timecop_reset_path %>
34
+ </p>
35
+ <% end -%>
36
+ </div>
37
+
38
+ <div id="railsCaddyEmail">
39
+ <h2>Sanitize Email</h2>
40
+ <p>All email sent to: <strong style="color: red;"><%= ActionMailer::Base.sanitized_recipients %></strong></p>
41
+ <% form_remote_tag :url => set_sanitize_email_address_path do -%>
42
+ <%= text_field_tag "value", "", :size => 15 %>
43
+ <p>
44
+ <%= submit_tag "Change Email" %>
45
+ <%= link_to_remote "Unset", :url => unset_sanitize_email_address_path %>
46
+ </p>
47
+ <% end -%>
48
+ </div>
49
+
50
+ <div id="railsCaddyStats">
51
+ <h2>Stats</h2>
52
+ </div>
53
+
54
+ </div>
55
+ </div>
56
+
57
+ </div>
@@ -0,0 +1,60 @@
1
+ <style type="text/css">
2
+ #railsCaddy {
3
+ text-align: left;
4
+ position: absolute;
5
+ width: auto;
6
+ height: auto;
7
+ top: 100px;
8
+ left: 0px;
9
+ z-index: 100;
10
+ font-family: Helvetica, Arial, Times;
11
+ }
12
+
13
+ #railsCaddyTab {
14
+ float: left;
15
+ height: 137px;
16
+ width: 28px;
17
+ text-decoration: none;
18
+ }
19
+
20
+ #railsCaddyTab img {
21
+ border: none;
22
+ }
23
+
24
+ #railsCaddyContents {
25
+ float: left;
26
+ overflow: hidden !important;
27
+ width: 200px;
28
+ }
29
+
30
+ #railsCaddyContentsInner {
31
+ width: 200px;
32
+ margin-top: 30px;
33
+ font-size: 12px;
34
+ }
35
+
36
+ #railsCaddyContentsInner > div {
37
+ border: solid 1px red;
38
+ }
39
+
40
+ #railsCaddyContentsInner h2 {
41
+ margin: 0px 0px 3px 0px;
42
+ padding: 2px;
43
+ background-color: #CC3400;
44
+ color: #FFFFFF;
45
+ font-size: 14px;
46
+ }
47
+
48
+ #railsCaddySession p {
49
+ margin-top: 0px;
50
+ margin-bottom: 4px;
51
+ }
52
+
53
+ #railsCaddySession p strong {
54
+ font-size: 110%;
55
+ }
56
+
57
+ #railsCaddySession a.x {
58
+ color: red;
59
+ }
60
+ </style>