rails-dev-tweaks 0.3.1

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.
@@ -0,0 +1,15 @@
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.
15
+
@@ -0,0 +1,97 @@
1
+ # rails-dev-tweaks
2
+ A collection of tweaks to improve your Rails (3.1+) development experience.
3
+
4
+ To install, simply add it to your gemfile:
5
+
6
+ gem 'rails-dev-tweaks', '~> 0.3.1'
7
+
8
+ At the moment, the current tweaks center around speeding up requests by giving granular control over which requests
9
+ cause the Rails autoloader to kick in:
10
+
11
+
12
+ # Granular Autoload
13
+ Rails' autoloading facility is a wonderful help for development mode, but sometimes it's a little overkill and ends up
14
+ hampering your rate of iteration while developing a Rails app. rails-dev-tweaks introduces granular control over which
15
+ kinds of requests are autoloaded.
16
+
17
+ However, why should you use request-based autoload control instead of smart autoloaders that check file modification
18
+ times, such as [rails-dev-boost](https://github.com/thedarkone/rails-dev-boost)? The primary worry with smart
19
+ autoloaders is that they have an extremely difficult time tracking all dependencies of a particular constant. This can
20
+ result in extremely confusing and difficult to debug issues; Theoretically, request-based autoloading should be a bit
21
+ less finicky.
22
+
23
+ You can specify autoload rules for your app via a configuration block in your application or environment configuration.
24
+ These rules are specified via exclusion (`skip`) and inclusion (`keep`). Rules defined later override those defined
25
+ before.
26
+
27
+ config.dev_tweaks.autoload_rules do
28
+ # You can used named matchers (see below). This particular matcher effectively clears any default matchers
29
+ keep :all
30
+
31
+ # Exclude all requests that begin with /search
32
+ skip '/search'
33
+ # But include routes that include smerch
34
+ keep /smerch/
35
+
36
+ # Use a block if you want to inspect the request
37
+ skip {|request| request.post?}
38
+ end
39
+
40
+ The default autoload rules should cover most development patterns:
41
+
42
+ config.dev_tweaks.autoload_rules do
43
+ keep :all
44
+
45
+ skip '/favicon.ico'
46
+ skip :assets
47
+ keep :forced
48
+ end
49
+
50
+ ## Named Matchers
51
+ Named matchers are classes defined under RailsDevTweaks::GranularAutoload::Matchers:: and simply define a call
52
+ method that is given a ActionDispatch::Request and returns true/false on whether that request matches. Match names
53
+ are converted into a module name via "#{name.to\_s.classify}Matcher". E.g. :assets will specify the
54
+ RailsDevTweaks::GranularAutoload::Matchers::AssetMatcher.
55
+
56
+ Any additional arguments given to a `skip` or `keep` call will be passed as initializer arguments to the matcher.
57
+
58
+ ### :all
59
+ Matches every request passed to it.
60
+
61
+ ### :assets
62
+ Rails 3.1 integrated [Sprockets](http://getsprockets.org/) as its asset packager. Unfortunately, since the asset
63
+ packager is mounted using the traditional Rails dispatching infrastructure, it's hidden behind the Rails autoloader
64
+ (unloader). This matcher will match any requests that are routed to Sprockets (specifically any mounted
65
+ Sprockets::Environment instance).
66
+
67
+ _The downside_ to this matcher is that your Rails environment won't reload until you make a regular request to the dev
68
+ server (which should be your usual request pattern, anyway). Assets still reload properly (unless you're referencing
69
+ your application's Ruby code).
70
+
71
+ ### :forced
72
+ To aid in live-debugging when you need to, this matcher will match any request that has `force_autoload` set as a
73
+ parameter (GET or POST), or that has the `Force-Autoload` header set to something.
74
+
75
+ If you are live-debugging jQuery ajax requests, this helpful snippet will turn on forced autoloading for the remainder
76
+ of the browser's session:
77
+
78
+ $.ajaxSetup({"beforeSend": function(xhr) {xhr.setRequestHeader("Force-Autoload", "true")} })
79
+
80
+ ### :path
81
+ Matches the path of the request via a regular expression.
82
+
83
+ keep :path, /thing/ # Match any request with "thing" in the path.
84
+
85
+ Note that `keep '/stuff'` is just shorthand for `keep :path, /^\/stuff/`. Similarly, `keep /thing/` is shorthand for
86
+ `keep :path, /thing/`
87
+
88
+ ### :xhr
89
+ Matches any XHR request (via request.xhr?). The assumption here is that you generally don't live-debug your XHR
90
+ requests, and are instead refreshing the page that kicks them off before running against new response code.
91
+
92
+
93
+ # License
94
+ rails-dev-tweaks is MIT licensed by Wavii, Inc. http://wavii.com
95
+
96
+ See the accompanying file, `MIT-LICENSE`, for the full text.
97
+
@@ -0,0 +1,2 @@
1
+ require 'bundler/gem_tasks'
2
+
@@ -0,0 +1,14 @@
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
14
+
@@ -0,0 +1,82 @@
1
+ class RailsDevTweaks::Configuration
2
+
3
+ attr_reader :granular_autoload_config
4
+
5
+ def initialize
6
+ @granular_autoload_config = GranularAutoloadConfiguration.new
7
+
8
+ # And set our defaults
9
+ self.autoload_rules do
10
+ keep :all
11
+
12
+ skip '/favicon.ico'
13
+ skip :assets
14
+ keep :forced
15
+ end
16
+ end
17
+
18
+ # Takes a block that configures the granular autoloader's rules.
19
+ def autoload_rules(&block)
20
+ @granular_autoload_config.instance_eval(&block)
21
+ end
22
+
23
+ class GranularAutoloadConfiguration
24
+
25
+ def initialize
26
+ # Each rule is a simple pair: [:skip, callable], [:keep, callable], etc.
27
+ @rules = []
28
+ end
29
+
30
+ def keep(*args, &block)
31
+ self.append_rule(:keep, *args, &block)
32
+ end
33
+
34
+ def skip(*args, &block)
35
+ self.append_rule(:skip, *args, &block)
36
+ end
37
+
38
+ def append_rule(rule_type, *args, &block)
39
+ unless rule_type == :skip || rule_type == :keep
40
+ raise TypeError, "Rule must be :skip or :keep. Got: #{rule_type.inspect}"
41
+ end
42
+
43
+ # Simple matcher blocks
44
+ if args.size == 0 && block.present?
45
+ @rules.unshift [rule_type, block]
46
+ return self
47
+ end
48
+
49
+ # String match shorthand
50
+ args[0] = /^#{args[0]}/ if args.size == 1 && args[0].kind_of?(String)
51
+
52
+ # Regex match shorthand
53
+ args = [:path, args[0]] if args.size == 1 && args[0].kind_of?(Regexp)
54
+
55
+ if args.size == 0 && block.blank?
56
+ raise TypeError, 'Cannot process autoload rule as specified. Expecting a named matcher (symbol), path prefix (string) or block'
57
+ end
58
+
59
+ # Named matcher
60
+ matcher_class = "RailsDevTweaks::GranularAutoload::Matchers::#{args[0].to_s.classify}Matcher".constantize
61
+ matcher = matcher_class.new(*args[1..-1])
62
+ raise TypeError, "Matchers must respond to :call. #{matcher.inspect} does not." unless matcher.respond_to? :call
63
+
64
+ @rules.unshift [rule_type, matcher]
65
+
66
+ self
67
+ end
68
+
69
+ def should_reload?(request)
70
+ @rules.each do |rule_type, callable|
71
+ return rule_type == :keep if callable.call(request)
72
+ end
73
+
74
+ # We default to reloading to preserve behavior, but we should never get to this unless the configuration is
75
+ # all sorts of horked.
76
+ true
77
+ end
78
+
79
+ end
80
+
81
+ end
82
+
@@ -0,0 +1,8 @@
1
+ class RailsDevTweaks::GranularAutoload::Matchers::AllMatcher
2
+
3
+ def call(request)
4
+ true
5
+ end
6
+
7
+ end
8
+
@@ -0,0 +1,29 @@
1
+ class RailsDevTweaks::GranularAutoload::Matchers::AssetMatcher
2
+
3
+ def call(request)
4
+ main_mount = request.headers['action_dispatch.routes'].set.recognize(request)
5
+
6
+ # Unwind until we have an actual app
7
+ while main_mount != nil
8
+ if main_mount.kind_of? Array
9
+ main_mount = main_mount.first
10
+
11
+ elsif main_mount.kind_of? Rack::Mount::Route
12
+ main_mount = main_mount.app
13
+
14
+ elsif main_mount.kind_of? Rack::Mount::Prefix
15
+ # Bah, no accessor here
16
+ main_mount = main_mount.instance_variable_get(:@app)
17
+
18
+ # Well, we got something
19
+ else
20
+ break
21
+ end
22
+ end
23
+
24
+ # what do we have?
25
+ main_mount.kind_of? Sprockets::Environment
26
+ end
27
+
28
+ end
29
+
@@ -0,0 +1,8 @@
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
8
+
@@ -0,0 +1,12 @@
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
12
+
@@ -0,0 +1,8 @@
1
+ class RailsDevTweaks::GranularAutoload::Matchers::XhrMatcher
2
+
3
+ def call(request)
4
+ request.xhr?
5
+ end
6
+
7
+ end
8
+
@@ -0,0 +1,37 @@
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
+ if self.class.processed_a_request? # No-op if this is the first request. The initializers take care of that one.
25
+ ActionDispatch::Reloader.cleanup!
26
+ ActionDispatch::Reloader.prepare!
27
+ end
28
+ self.class.processed_a_request = true
29
+
30
+ else
31
+ Rails.logger.info 'RailsDevTweaks: Skipping ActionDispatch::Reloader hooks for this request.'
32
+ end
33
+
34
+ return @app.call(env)
35
+ end
36
+ end
37
+
@@ -0,0 +1,14 @@
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
14
+
@@ -0,0 +1,4 @@
1
+ module RailsDevTweaks
2
+ VERSION = '0.3.1'
3
+ end
4
+
metadata ADDED
@@ -0,0 +1,77 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails-dev-tweaks
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Wavii, Inc.
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-07-12 00:00:00.000000000 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: rails
17
+ requirement: &2167156100 !ruby/object:Gem::Requirement
18
+ none: false
19
+ requirements:
20
+ - - ~>
21
+ - !ruby/object:Gem::Version
22
+ version: 3.1.0.rc4
23
+ type: :runtime
24
+ prerelease: false
25
+ version_requirements: *2167156100
26
+ description: A collection of tweaks to improve your Rails (3.1+) development experience.
27
+ email:
28
+ - info@wavii.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - lib/rails-dev-tweaks.rb
34
+ - lib/rails_dev_tweaks/configuration.rb
35
+ - lib/rails_dev_tweaks/granular_autoload/matchers/all_matcher.rb
36
+ - lib/rails_dev_tweaks/granular_autoload/matchers/asset_matcher.rb
37
+ - lib/rails_dev_tweaks/granular_autoload/matchers/forced_matcher.rb
38
+ - lib/rails_dev_tweaks/granular_autoload/matchers/path_matcher.rb
39
+ - lib/rails_dev_tweaks/granular_autoload/matchers/xhr_matcher.rb
40
+ - lib/rails_dev_tweaks/granular_autoload/middleware.rb
41
+ - lib/rails_dev_tweaks/railtie.rb
42
+ - lib/rails_dev_tweaks/version.rb
43
+ - MIT-LICENSE
44
+ - Rakefile
45
+ - README.md
46
+ has_rdoc: true
47
+ homepage: http://wavii.com/
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ segments:
60
+ - 0
61
+ hash: -1289302315746076260
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ! '>='
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ segments:
69
+ - 0
70
+ hash: -1289302315746076260
71
+ requirements: []
72
+ rubyforge_project: rails-dev-tweaks
73
+ rubygems_version: 1.6.2
74
+ signing_key:
75
+ specification_version: 3
76
+ summary: A collection of tweaks to improve your Rails (3.1+) development experience.
77
+ test_files: []