rails-dev-tweaks-arturo 0.6.2

Sign up to get free protection for your applications and to get access to all the features.
data/MIT-LICENSE ADDED
@@ -0,0 +1,14 @@
1
+ Copyright (c) 2011 Wavii, inc. http://wavii.com/
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
4
+ documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
5
+ rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
6
+ persons to whom the Software is furnished to do so, subject to the following conditions:
7
+
8
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
9
+ Software.
10
+
11
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
12
+ WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
13
+ COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
14
+ OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,134 @@
1
+ rails-dev-tweaks
2
+ ================
3
+
4
+ A collection of tweaks to improve your Rails (3.1+) development experience.
5
+
6
+ To install, simply add it to your gemfile:
7
+
8
+ gem 'rails-dev-tweaks', '~> 0.6.2'
9
+
10
+ And review the following section to make sure that `rails-dev-tweaks` is
11
+ configured the way you expect:
12
+
13
+
14
+ Intended Usage (and Caveats)
15
+ ----------------------------
16
+
17
+ This gem is intended to provide a default configuration that covers most rails
18
+ apps:
19
+
20
+ * _All_ asset requests _will not_ reload your app's code. This is probably only
21
+ a problem if you are using custom sass functions, or otherwise referencing
22
+ your app from within assets.
23
+
24
+ * XHR requests **will reload** your app's code. (This was not the case in prior
25
+ versions of `rails-dev-tweaks`)
26
+
27
+ If any of these points don't work out for you, don't fret! You can override the
28
+ defaults with some simple configuration tweaks to your environment. Read on:
29
+
30
+
31
+ Granular Autoload
32
+ =================
33
+
34
+ You can specify autoload rules for your app via a configuration block in your
35
+ application or environment configuration. These rules are specified via
36
+ exclusion (`skip`) and inclusion (`keep`). Rules defined later override those
37
+ defined before.
38
+
39
+ config.dev_tweaks.autoload_rules do
40
+ # You can used named matchers (see below). This particular matcher
41
+ # effectively clears any default matchers
42
+ keep :all
43
+
44
+ # Exclude all requests that begin with /search
45
+ skip '/search'
46
+ # But include routes that include smerch
47
+ keep /smerch/
48
+
49
+ # Use a block if you want to inspect the request
50
+ skip {|request| request.post?}
51
+ end
52
+
53
+ The default autoload rules should cover most development patterns:
54
+
55
+ config.dev_tweaks.autoload_rules do
56
+ keep :all
57
+
58
+ skip '/favicon.ico'
59
+ skip :assets
60
+ skip :xhr
61
+ keep :forced
62
+ end
63
+
64
+ By default, every request that skips the autoload hooks will generate an
65
+ additional log line saying so in an effort to be transparent about what is going
66
+ on. If you prefer, you can disable that log message to keep things a bit more
67
+ tidy in your logs:
68
+
69
+ config.dev_tweaks.log_autoload_notice = false
70
+
71
+
72
+ Named Matchers
73
+ --------------
74
+
75
+ Named matchers are classes defined under
76
+ RailsDevTweaks::GranularAutoload::Matchers:: and simply define a call method
77
+ that is given a ActionDispatch::Request and returns true/false on whether that
78
+ request matches. Match names are converted into a module name via
79
+ "#{name.to\_s.classify}Matcher". E.g. :assets will specify
80
+ `RailsDevTweaks::GranularAutoload::Matchers::AssetMatcher`.
81
+
82
+ Any additional arguments given to a `skip` or `keep` call will be passed as
83
+ initializer arguments to the matcher.
84
+
85
+
86
+ ### :all
87
+
88
+ Matches every request passed to it.
89
+
90
+
91
+ ### :assets
92
+
93
+ Rails 3.1 integrated [Sprockets](http://getsprockets.org/) as its asset
94
+ packager. Unfortunately, since the asset packager is mounted using the
95
+ traditional Rails dispatching infrastructure, it's hidden behind the Rails
96
+ autoloader (unloader). This matcher will match any requests that are routed to
97
+ Sprockets (specifically any mounted Sprockets::Base instance).
98
+
99
+
100
+ ### :forced
101
+
102
+ To aid in live-debugging when you need to, this matcher will match any request
103
+ that has `force_autoload` set as a parameter (GET or POST), or that has the
104
+ `Force-Autoload` header set to something.
105
+
106
+ If you are live-debugging jQuery ajax requests, this helpful snippet will turn
107
+ on forced autoloading for the remainder of the browser's session:
108
+
109
+ $.ajaxSetup({"beforeSend": function(xhr) {xhr.setRequestHeader("Force-Autoload", "true")} })
110
+
111
+
112
+ ### :path
113
+
114
+ Matches the path of the request via a regular expression.
115
+
116
+ keep :path, /thing/ # Match any request with "thing" in the path.
117
+
118
+ Note that `keep '/stuff'` is just shorthand for `keep :path, /^\/stuff/`.
119
+ Similarly, `keep /thing/` is shorthand for `keep :path, /thing/`
120
+
121
+
122
+ ### :xhr
123
+
124
+ Matches any XHR request (via request.xhr?). The assumption here is that you
125
+ generally don't live-debug your XHR requests, and are instead refreshing the
126
+ page that kicks them off before running against new response code.
127
+
128
+
129
+ License
130
+ =======
131
+
132
+ `rails-dev-tweaks` is MIT licensed by Wavii, Inc. http://wavii.com
133
+
134
+ See the accompanying file, `MIT-LICENSE`, for the full text.
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,13 @@
1
+ require 'active_support'
2
+ require 'active_support/dependencies'
3
+
4
+ module RailsDevTweaks
5
+ LIB_PATH = File.expand_path('..', __FILE__)
6
+ end
7
+
8
+ # Ironically, we use autoloading ourselves to enforce our file structure, and less typing.
9
+ ActiveSupport::Dependencies.autoload_paths << RailsDevTweaks::LIB_PATH
10
+ ActiveSupport::Dependencies.autoload_once_paths << RailsDevTweaks::LIB_PATH # But don't allow *auto-reloading*!
11
+
12
+ # Reference the railtie to force it to load
13
+ RailsDevTweaks::Railtie
@@ -0,0 +1,87 @@
1
+ class RailsDevTweaks::Configuration
2
+
3
+ # By default, we log a notice on each request that has its to_prepare hooks skipped, you can
4
+ # disable that if you choose!
5
+ attr_accessor :log_autoload_notice
6
+
7
+ attr_reader :granular_autoload_config
8
+
9
+ def initialize
10
+ @log_autoload_notice = true
11
+
12
+ @granular_autoload_config = GranularAutoloadConfiguration.new
13
+
14
+ # And set our defaults
15
+ self.autoload_rules do
16
+ keep :all
17
+
18
+ skip '/favicon.ico'
19
+ skip :assets
20
+ keep :forced
21
+ end
22
+ end
23
+
24
+ # Takes a block that configures the granular autoloader's rules.
25
+ def autoload_rules(&block)
26
+ @granular_autoload_config.instance_eval(&block)
27
+ end
28
+
29
+ class GranularAutoloadConfiguration
30
+
31
+ def initialize
32
+ # Each rule is a simple pair: [:skip, callable], [:keep, callable], etc.
33
+ @rules = []
34
+ end
35
+
36
+ def keep(*args, &block)
37
+ self.append_rule(:keep, *args, &block)
38
+ end
39
+
40
+ def skip(*args, &block)
41
+ self.append_rule(:skip, *args, &block)
42
+ end
43
+
44
+ def append_rule(rule_type, *args, &block)
45
+ unless rule_type == :skip || rule_type == :keep
46
+ raise TypeError, "Rule must be :skip or :keep. Got: #{rule_type.inspect}"
47
+ end
48
+
49
+ # Simple matcher blocks
50
+ if args.size == 0 && block.present?
51
+ @rules.unshift [rule_type, block]
52
+ return self
53
+ end
54
+
55
+ # String match shorthand
56
+ args[0] = /^#{args[0]}/ if args.size == 1 && args[0].kind_of?(String)
57
+
58
+ # Regex match shorthand
59
+ args = [:path, args[0]] if args.size == 1 && args[0].kind_of?(Regexp)
60
+
61
+ if args.size == 0 && block.blank?
62
+ raise TypeError, 'Cannot process autoload rule as specified. Expecting a named matcher (symbol), path prefix (string) or block'
63
+ end
64
+
65
+ # Named matcher
66
+ matcher_class = "RailsDevTweaks::GranularAutoload::Matchers::#{args[0].to_s.classify}Matcher".constantize
67
+ matcher = matcher_class.new(*args[1..-1])
68
+ raise TypeError, "Matchers must respond to :call. #{matcher.inspect} does not." unless matcher.respond_to? :call
69
+
70
+ @rules.unshift [rule_type, matcher]
71
+
72
+ self
73
+ end
74
+
75
+ def should_reload?(request)
76
+ @rules.each do |rule_type, callable|
77
+ return rule_type == :keep if callable.call(request)
78
+ end
79
+
80
+ # We default to reloading to preserve behavior, but we should never get to this unless the configuration is
81
+ # all sorts of horked.
82
+ true
83
+ end
84
+
85
+ end
86
+
87
+ end
@@ -0,0 +1,7 @@
1
+ class RailsDevTweaks::GranularAutoload::Matchers::AllMatcher
2
+
3
+ def call(request)
4
+ true
5
+ end
6
+
7
+ end
@@ -0,0 +1,46 @@
1
+ class RailsDevTweaks::GranularAutoload::Matchers::AssetMatcher
2
+
3
+ def call(request)
4
+ route_engine = request.headers['action_dispatch.routes']
5
+
6
+ if route_engine.respond_to?(:router)
7
+ mounted_app = journey_find_app(route_engine.router, request)
8
+ else
9
+ mounted_app = rack_find_app(route_engine.set.dup, request)
10
+ end
11
+
12
+ # What do we have?
13
+ mounted_app.is_a? Sprockets::Base
14
+ end
15
+
16
+ def journey_find_app(router, request)
17
+ router.recognize(request) do |route, *args|
18
+ return route.app
19
+ end
20
+ end
21
+
22
+ def rack_find_app(router, request)
23
+ main_mount = router.recognize(request)
24
+
25
+ # Unwind until we have an actual app
26
+ while main_mount != nil
27
+ if main_mount.is_a? Array
28
+ main_mount = main_mount.first
29
+
30
+ elsif main_mount.is_a? Rack::Mount::Route
31
+ main_mount = main_mount.app
32
+
33
+ elsif main_mount.is_a? Rack::Mount::Prefix
34
+ # Bah, no accessor here
35
+ main_mount = main_mount.instance_variable_get(:@app)
36
+
37
+ # Well, we got something
38
+ else
39
+ break
40
+ end
41
+ end
42
+
43
+ main_mount
44
+ end
45
+
46
+ end
@@ -0,0 +1,7 @@
1
+ class RailsDevTweaks::GranularAutoload::Matchers::ForcedMatcher
2
+
3
+ def call(request)
4
+ request.headers['Force-Autoload'] || request.params.has_key?(:force_autoload)
5
+ end
6
+
7
+ end
@@ -0,0 +1,11 @@
1
+ class RailsDevTweaks::GranularAutoload::Matchers::PathMatcher
2
+
3
+ def initialize(regex)
4
+ @regex = regex
5
+ end
6
+
7
+ def call(request)
8
+ @regex =~ request.fullpath
9
+ end
10
+
11
+ end
@@ -0,0 +1,7 @@
1
+ class RailsDevTweaks::GranularAutoload::Matchers::XhrMatcher
2
+
3
+ def call(request)
4
+ request.xhr?
5
+ end
6
+
7
+ end
@@ -0,0 +1,48 @@
1
+ # Here's an idea, let's not reload the entire dev environment for each asset request. Let's only do that on regular
2
+ # content requests.
3
+ class RailsDevTweaks::GranularAutoload::Middleware
4
+
5
+ # Don't cleanup before the very first request
6
+ class << self
7
+ attr_writer :processed_a_request
8
+ def processed_a_request?
9
+ @processed_a_request
10
+ end
11
+ end
12
+
13
+ def initialize(app)
14
+ @app = app
15
+ end
16
+
17
+ def call(env)
18
+ request = ActionDispatch::Request.new(env.dup)
19
+
20
+ # reload, or no?
21
+ if Rails.application.config.dev_tweaks.granular_autoload_config.should_reload?(request)
22
+ # Confusingly, we flip the request prepare/cleanup life cycle around so that we're only cleaning up on those
23
+ # requests that want to be reloaded
24
+
25
+ # No-op if this is the first request. The initializers take care of that one.
26
+ if self.class.processed_a_request? && reload_dependencies?
27
+ ActionDispatch::Reloader.cleanup!
28
+ ActionDispatch::Reloader.prepare!
29
+ end
30
+ self.class.processed_a_request = true
31
+
32
+ elsif Rails.application.config.dev_tweaks.log_autoload_notice
33
+ Rails.logger.info 'RailsDevTweaks: Skipping ActionDispatch::Reloader hooks for this request.'
34
+ end
35
+
36
+ return @app.call(env)
37
+ end
38
+
39
+ private
40
+
41
+ def reload_dependencies?
42
+ application = Rails.application
43
+
44
+ # Rails 3.2 defines reload_dependencies? and it only reloads if reload_dependencies? returns true.
45
+ (!application.class.method_defined?(:reload_dependencies?) ||
46
+ application.send(:reload_dependencies?))
47
+ end
48
+ end
@@ -0,0 +1,13 @@
1
+ class RailsDevTweaks::Railtie < Rails::Railtie
2
+
3
+ config.dev_tweaks = RailsDevTweaks::Configuration.new
4
+
5
+ config.before_initialize do |app|
6
+ # We can't inspect the stack because it's deferred... For now, just assume we have it when config.cache_clasess is
7
+ # falsy; which should always be the case in the current version of rails anyway.
8
+ unless app.config.cache_classes
9
+ app.config.middleware.swap ActionDispatch::Reloader, RailsDevTweaks::GranularAutoload::Middleware
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,3 @@
1
+ module RailsDevTweaks
2
+ VERSION = '0.6.2'
3
+ end
metadata ADDED
@@ -0,0 +1,91 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails-dev-tweaks-arturo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.6.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Wavii, Inc.
9
+ - Arturo Pie
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2012-10-25 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: railties
17
+ requirement: !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: '3'
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ~>
29
+ - !ruby/object:Gem::Version
30
+ version: '3'
31
+ - !ruby/object:Gem::Dependency
32
+ name: actionpack
33
+ requirement: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ~>
37
+ - !ruby/object:Gem::Version
38
+ version: '3'
39
+ type: :runtime
40
+ prerelease: false
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ~>
45
+ - !ruby/object:Gem::Version
46
+ version: '3'
47
+ description: A collection of tweaks to improve your Rails (3.1+) development experience.
48
+ email:
49
+ - info@wavii.com
50
+ executables: []
51
+ extensions: []
52
+ extra_rdoc_files: []
53
+ files:
54
+ - lib/rails-dev-tweaks.rb
55
+ - lib/rails_dev_tweaks/version.rb
56
+ - lib/rails_dev_tweaks/railtie.rb
57
+ - lib/rails_dev_tweaks/configuration.rb
58
+ - lib/rails_dev_tweaks/granular_autoload/middleware.rb
59
+ - lib/rails_dev_tweaks/granular_autoload/matchers/all_matcher.rb
60
+ - lib/rails_dev_tweaks/granular_autoload/matchers/xhr_matcher.rb
61
+ - lib/rails_dev_tweaks/granular_autoload/matchers/forced_matcher.rb
62
+ - lib/rails_dev_tweaks/granular_autoload/matchers/path_matcher.rb
63
+ - lib/rails_dev_tweaks/granular_autoload/matchers/asset_matcher.rb
64
+ - MIT-LICENSE
65
+ - Rakefile
66
+ - README.md
67
+ homepage: http://wavii.com/
68
+ licenses: []
69
+ post_install_message:
70
+ rdoc_options: []
71
+ require_paths:
72
+ - lib
73
+ required_ruby_version: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: '0'
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ none: false
81
+ requirements:
82
+ - - ! '>='
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubyforge_project: rails-dev-tweaks
87
+ rubygems_version: 1.8.24
88
+ signing_key:
89
+ specification_version: 3
90
+ summary: A collection of tweaks to improve your Rails (3.1+) development experience.
91
+ test_files: []