motorhead 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +13 -0
- data/.travis.yml +4 -0
- data/Gemfile +4 -0
- data/MIT-LICENSE +21 -0
- data/README.md +218 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/gemfiles/Gemfile-rails.4.2.x +11 -0
- data/lib/generators/motorhead/controller_generator.rb +29 -0
- data/lib/generators/motorhead/templates/controller.rb +15 -0
- data/lib/generators/motorhead/templates/lib/%name%/engine.rb +9 -0
- data/lib/generators/motorhead_generator.rb +60 -0
- data/lib/motorhead.rb +13 -0
- data/lib/motorhead/abstract_controller.rb +73 -0
- data/lib/motorhead/action_view.rb +47 -0
- data/lib/motorhead/config.rb +13 -0
- data/lib/motorhead/engine.rb +28 -0
- data/lib/motorhead/version.rb +3 -0
- data/motorhead.gemspec +29 -0
- metadata +163 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 598e8175e3cf77c2e86bd359dc1edb196a1ac74b
|
4
|
+
data.tar.gz: 2cb3e49446e77f6a5c33b1d84b2ff2a4e560a404
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 736b9387276958a6ac86223a5ae45b81592853cb596fcaa28abf90b3d19bcf18fb9cffb911786ff5f461ad8ae2e6d14d4fe5becbe06d17f95a01702842821d8d
|
7
|
+
data.tar.gz: 7aa2c8e1569fcc61ac700e59db2ef42fd6c4dd4e8061fe24741f9fce6742e393cd7bff7498dbec4147adac6321b59fc90ac52a1a6cf1cc7776e5703e0c9a8607
|
data/.gitignore
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Akira Matsuda
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,218 @@
|
|
1
|
+
# Motorhead
|
2
|
+
|
3
|
+
Motorhead is a prototyping framework for Rails.
|
4
|
+
It's something akin to "feature toggle".
|
5
|
+
It can be used for "A/B testing" as well.
|
6
|
+
But essentially, the main purpose of this framework is to provide a way to rapidly and safely deliver new features to the production environment.
|
7
|
+
|
8
|
+
|
9
|
+
## Installation
|
10
|
+
|
11
|
+
Bundle into your Rails app.
|
12
|
+
|
13
|
+
|
14
|
+
## Features
|
15
|
+
|
16
|
+
### Isolated Engine
|
17
|
+
|
18
|
+
Motorhead helps you mounting specially creafted Isolated Engines onto the main Rails app.
|
19
|
+
An engine can contain whole MVC conponents, which means that you can encapsulate everything that are needed for your new feature under one single directory.
|
20
|
+
This helps your team creating multiple new features simultaneously without causing code conflict.
|
21
|
+
|
22
|
+
### Conditional Execution
|
23
|
+
|
24
|
+
Each Motorhead engine can be configured to be enabled/disabled.
|
25
|
+
The condition is not just a flag but can be a Ruby Proc which will be dynamically evaluated on each request in the controller context.
|
26
|
+
|
27
|
+
### Error-proof
|
28
|
+
|
29
|
+
If any RuntimeError happens inside an engine on the production environment, Motorhead absorbs the error and executes the appropriate fallback code so that the end users would never even notice the occurrence of the error.
|
30
|
+
|
31
|
+
### Extending Action Methods in the Main App
|
32
|
+
|
33
|
+
Motorhead provides an interface to override the main app's controller actions.
|
34
|
+
|
35
|
+
### Partially Extending Views in the Main App
|
36
|
+
|
37
|
+
Motorhead provides a hook to partially overwrite any part of your existing view.
|
38
|
+
|
39
|
+
|
40
|
+
## Structure
|
41
|
+
|
42
|
+
main_app
|
43
|
+
├── Gemfile
|
44
|
+
├── Gemfile.lock
|
45
|
+
├── Rakefile
|
46
|
+
├── app
|
47
|
+
│ ├── assets
|
48
|
+
│ ├── controllers
|
49
|
+
│ ├── engines
|
50
|
+
│ │ ├── my_awesome_new_feature
|
51
|
+
│ │ │ ├── app
|
52
|
+
│ │ │ │ ├── assets
|
53
|
+
│ │ │ │ ├── controllers
|
54
|
+
│ │ │ │ │ └── my_awesome_new_feature
|
55
|
+
│ │ │ │ │ └── welcome_controller.rb
|
56
|
+
│ │ │ │ ├── helpers
|
57
|
+
│ │ │ │ │ └── my_awesome_new_feature
|
58
|
+
│ │ │ │ │ └── welcome_helper.rb
|
59
|
+
│ │ │ │ ├── mailers
|
60
|
+
│ │ │ │ ├── models
|
61
|
+
│ │ │ │ └── views
|
62
|
+
│ │ │ │ ├── layouts
|
63
|
+
│ │ │ │ │ └── my_awesome_new_feature
|
64
|
+
│ │ │ │ │ └── application.html.erb
|
65
|
+
│ │ │ │ └── my_awesome_new_feature
|
66
|
+
│ │ │ │ └── welcome
|
67
|
+
│ │ │ ├── config
|
68
|
+
│ │ │ │ └── routes.rb
|
69
|
+
│ │ │ ├── lib
|
70
|
+
│ │ │ │ ├── my_awesome_new_feature
|
71
|
+
│ │ │ │ │ └── engine.rb
|
72
|
+
│ │ │ │ ├── my_awesome_new_feature.rb
|
73
|
+
│ │ │ │ └── tasks
|
74
|
+
│ │ │ ├── my_awesome_new_feature.gemspec
|
75
|
+
│ │ │ └── test
|
76
|
+
│ │ └── yet_another_new_feature
|
77
|
+
│ │ ├── app
|
78
|
+
│ │ ...
|
79
|
+
│ ├── helpers
|
80
|
+
│ ├── mailers
|
81
|
+
│ ├── models
|
82
|
+
│ └── views
|
83
|
+
├── bin
|
84
|
+
├── config
|
85
|
+
├── db
|
86
|
+
...
|
87
|
+
|
88
|
+
|
89
|
+
## Components
|
90
|
+
|
91
|
+
### lib/ENGINE\_NAME/engine.rb
|
92
|
+
|
93
|
+
Put `active_if` directive inside the Engine class. The whole engine will only be executed if the block is evaluated to be truthy on runtime.
|
94
|
+
|
95
|
+
Example:
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
# app/engines/my_awesome_new_feature/config/routes.rb
|
99
|
+
module MyAwesomeNewFeature
|
100
|
+
class Engine < ::Rails::Engine
|
101
|
+
include Motorhead::Engine
|
102
|
+
|
103
|
+
# this whole engine will be executed only when logged in as admin users
|
104
|
+
active_if { current_user.admin? }
|
105
|
+
end
|
106
|
+
end
|
107
|
+
```
|
108
|
+
|
109
|
+
### routes.rb
|
110
|
+
|
111
|
+
All routes in engines' routes.rb will be automatically prepended to the main app's Routes.
|
112
|
+
|
113
|
+
|
114
|
+
### Controllers
|
115
|
+
|
116
|
+
Controllers can be a normal Engine controller.
|
117
|
+
Or, you can craft a controller class inheriting a controller that exists in the main app, and overriding some action methods.
|
118
|
+
From inside the actions in engines, you can call the main app's action via `super`.
|
119
|
+
|
120
|
+
Example:
|
121
|
+
|
122
|
+
```ruby
|
123
|
+
# app/engines/my_awesome_new_feature/app/controllers/my_awesome_new_feature/welcome_controller.rb
|
124
|
+
class MyAwesomeNewFeature::WelcomeController < ::WelcomeController
|
125
|
+
include Motorhead::Controller
|
126
|
+
|
127
|
+
def index
|
128
|
+
# invoking the main app's action first
|
129
|
+
super
|
130
|
+
|
131
|
+
# adding some more business logic
|
132
|
+
@notifications = Notification.for current_user
|
133
|
+
end
|
134
|
+
end
|
135
|
+
```
|
136
|
+
|
137
|
+
|
138
|
+
### Views
|
139
|
+
|
140
|
+
When an engine renders the views, it looks up app/views/ENGINE\_NAME/ directory first, then the main app's view directory next. This way you can overwrite views per template/partial file.
|
141
|
+
Also, Motorhead adds new `:engine` option to `render` method, which enables you to explicitly inject a piece of HTML from an engine into any place of the app.
|
142
|
+
`render :engine` takes an `ENGINE_NAME/view_path' parameter.
|
143
|
+
|
144
|
+
Example:
|
145
|
+
|
146
|
+
```haml
|
147
|
+
# app/engines/my_awesome_new_feature/app/views/my_awesome_new_feature/welcome/_index.html.haml
|
148
|
+
.new_feature
|
149
|
+
Some contents for new feature
|
150
|
+
|
151
|
+
# app/views/welcome/index.html.haml
|
152
|
+
= render engine: 'my_awesome_new_feature/welcome/index' do
|
153
|
+
Some contents that will be shown by default
|
154
|
+
```
|
155
|
+
|
156
|
+
|
157
|
+
## Generators
|
158
|
+
|
159
|
+
Motorhead provides some handy code generators.
|
160
|
+
|
161
|
+
### Generating an engine
|
162
|
+
|
163
|
+
```ruby
|
164
|
+
% rails g motorhead ENGINE_NAME
|
165
|
+
```
|
166
|
+
|
167
|
+
Example:
|
168
|
+
|
169
|
+
```ruby
|
170
|
+
% rails g motorhead my_awesome_new_feature
|
171
|
+
```
|
172
|
+
|
173
|
+
This generates a motorhead Engine in
|
174
|
+
~/app/engines/my\_awesome\_new\_feature/ directory.
|
175
|
+
|
176
|
+
### Generating an engine + a controller extension that extends an existing controller
|
177
|
+
|
178
|
+
|
179
|
+
```ruby
|
180
|
+
% rails g motorhead ENGINE_NAME CONTROLLER_NAME [action action] [options]
|
181
|
+
```
|
182
|
+
|
183
|
+
Example:
|
184
|
+
|
185
|
+
```ruby
|
186
|
+
% rails g motorhead my_awesome_new_feature welcome index
|
187
|
+
```
|
188
|
+
|
189
|
+
This generates a motorhead Engine in ~/app/engines/my\_awesome\_new\_feature/ directory. Plus, a controller that extends WelcomeController and implements index action inside the Engine.
|
190
|
+
|
191
|
+
|
192
|
+
|
193
|
+
|
194
|
+
|
195
|
+
|
196
|
+
|
197
|
+
|
198
|
+
## Contributing
|
199
|
+
|
200
|
+
Pull requests are welcome on GitHub at https://github.com/amatsuda/motorhead.
|
201
|
+
|
202
|
+
|
203
|
+
## Todo
|
204
|
+
|
205
|
+
* Better generator
|
206
|
+
|
207
|
+
* Model extension
|
208
|
+
|
209
|
+
* Documentation
|
210
|
+
|
211
|
+
|
212
|
+
## Special Thanks
|
213
|
+
|
214
|
+
This product is deeply inspired by [Chanko](http://cookpad.github.io/chanko/).
|
215
|
+
|
216
|
+
## License
|
217
|
+
|
218
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "motorhead"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
@@ -0,0 +1,11 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gemspec :path => '../'
|
4
|
+
|
5
|
+
gem 'rails', '~> 4.2.4'
|
6
|
+
gem 'controller_extension', path: '../test/dummy_app/app/engines/controller_extension'
|
7
|
+
gem 'controller_fallback', path: '../test/dummy_app/app/engines/controller_fallback'
|
8
|
+
gem 'view_render_fallback', path: '../test/dummy_app/app/engines/view_render_fallback'
|
9
|
+
gem 'routes_fallback', path: '../test/dummy_app/app/engines/routes_fallback'
|
10
|
+
gem 'italian', path: '../test/dummy_app/app/engines/italian'
|
11
|
+
gem 'spanish', path: '../test/dummy_app/app/engines/spanish'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rails/generators/rails/controller/controller_generator'
|
2
|
+
|
3
|
+
module Motorhead
|
4
|
+
module Generators
|
5
|
+
class ControllerGenerator < ::Rails::Generators::ControllerGenerator
|
6
|
+
source_root ::Rails::Generators::ControllerGenerator.source_root
|
7
|
+
|
8
|
+
remove_hook_for :template_engine, :test_framework
|
9
|
+
|
10
|
+
class << self
|
11
|
+
def source_paths
|
12
|
+
[File.expand_path('../templates', __FILE__), *super]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# override
|
17
|
+
def create_controller_files
|
18
|
+
@destination_stack[@destination_stack.size - 1] = File.join @destination_stack.last, 'app/engines', class_path
|
19
|
+
template 'controller.rb', File.join('app/controllers', class_path, "#{file_name}_controller.rb")
|
20
|
+
end
|
21
|
+
|
22
|
+
# override
|
23
|
+
private
|
24
|
+
def generate_routing_code(action)
|
25
|
+
"get '#{file_name}/#{action}'"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<% if namespaced? -%>
|
2
|
+
require_dependency "<%= namespaced_path %>/application_controller"
|
3
|
+
|
4
|
+
<% end -%>
|
5
|
+
<% module_namespacing do -%>
|
6
|
+
class <%= class_name %>Controller < ::<%= file_name.camelize %>Controller
|
7
|
+
include Motorhead::Controller
|
8
|
+
|
9
|
+
<% actions.each do |action| -%>
|
10
|
+
def <%= action %>
|
11
|
+
end
|
12
|
+
<%= "\n" unless action == actions.last -%>
|
13
|
+
<% end -%>
|
14
|
+
end
|
15
|
+
<% end -%>
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'rails/generators/rails/plugin/plugin_generator'
|
2
|
+
|
3
|
+
class MotorheadGenerator < ::Rails::Generators::PluginGenerator
|
4
|
+
class EngineBuilder < ::Rails::PluginBuilder
|
5
|
+
def readme() end
|
6
|
+
def rakefile() end
|
7
|
+
end
|
8
|
+
|
9
|
+
argument :base_controller, type: :string, optional: true, banner: 'base controller'
|
10
|
+
argument :actions, type: :array, default: [], banner: "action action"
|
11
|
+
source_root ::Rails::Generators::PluginGenerator.source_root
|
12
|
+
|
13
|
+
class << self
|
14
|
+
def source_paths
|
15
|
+
[File.expand_path('../motorhead/templates', __FILE__), *super]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(*args)
|
20
|
+
options = args.extract_options!
|
21
|
+
options[:destination_root] = 'app/engines'
|
22
|
+
super(*args, options)
|
23
|
+
options = @options.dup
|
24
|
+
options[:mountable] = options[:skip_bundle] = options[:skip_test_unit] = options[:skip_git] = options[:skip_gemfile] = true
|
25
|
+
@options = options.freeze
|
26
|
+
end
|
27
|
+
|
28
|
+
def get_builder_class
|
29
|
+
EngineBuilder
|
30
|
+
end
|
31
|
+
|
32
|
+
# override
|
33
|
+
def create_bin_files
|
34
|
+
end
|
35
|
+
|
36
|
+
def put_litter_in_its_place
|
37
|
+
remove_file 'MIT-LICENSE'
|
38
|
+
remove_file "app/controllers/#{name}/application_controller.rb"
|
39
|
+
remove_file "lib/tasks"
|
40
|
+
end
|
41
|
+
|
42
|
+
def untodo_gemspec
|
43
|
+
gemspec = "#{name}.gemspec"
|
44
|
+
gsub_file gemspec, /"TODO.*?"/, '""'
|
45
|
+
end
|
46
|
+
|
47
|
+
def bundle_to_parent
|
48
|
+
gemfile = Rails.root + 'Gemfile'
|
49
|
+
append_to_file gemfile, "gem '#{name}', path: '#{destination_root}'\n" if gemfile.exist?
|
50
|
+
end
|
51
|
+
|
52
|
+
def generate_controller
|
53
|
+
if base_controller
|
54
|
+
Dir.chdir destination_root do
|
55
|
+
#FIXME call the controller generator directly
|
56
|
+
puts `rails g motorhead:controller #{name}/#{base_controller} #{actions * ' '}`
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/motorhead.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require "motorhead/version"
|
2
|
+
require 'motorhead/config'
|
3
|
+
|
4
|
+
module Motorhead
|
5
|
+
class Railtie < ::Rails::Railtie
|
6
|
+
ActiveSupport.on_load :action_controller do
|
7
|
+
require 'motorhead/abstract_controller'
|
8
|
+
end
|
9
|
+
ActiveSupport.on_load :action_view do
|
10
|
+
require 'motorhead/action_view'
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module Motorhead
|
2
|
+
module Helpers
|
3
|
+
module UrlHelper
|
4
|
+
#FIXME there has to be a better way doing this...
|
5
|
+
def method_missing(meth, *args, &block)
|
6
|
+
if main_app.routes.url_helpers.instance_methods.include? meth
|
7
|
+
main_app.send meth, *args, &block
|
8
|
+
else
|
9
|
+
super
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
module Controller
|
16
|
+
extend ActiveSupport::Concern
|
17
|
+
|
18
|
+
included do
|
19
|
+
helper Motorhead::Helpers::UrlHelper
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module AbstractController
|
24
|
+
def send_action(method_name, *args)
|
25
|
+
if self.is_a?(Motorhead::Controller)
|
26
|
+
begin
|
27
|
+
super
|
28
|
+
@_motorhead_action_successfully_finished = true
|
29
|
+
env['motorhead_view_assigns'] = view_assigns
|
30
|
+
rescue => e
|
31
|
+
(self.class.parent::Engine.on_error || Motorhead.config.on_error).call(e)
|
32
|
+
end
|
33
|
+
else
|
34
|
+
if env.key? 'motorhead_render_result'
|
35
|
+
headers.delete 'X-Cascade'
|
36
|
+
ret = env.delete 'motorhead_render_result'
|
37
|
+
self.response_body = ret
|
38
|
+
else
|
39
|
+
super
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
module ActionController
|
46
|
+
def process_action(*args)
|
47
|
+
if self.is_a?(Motorhead::Controller)
|
48
|
+
headers['X-Cascade'] = 'pass'
|
49
|
+
if self.class.parent::Engine.active?(self)
|
50
|
+
super
|
51
|
+
end
|
52
|
+
else
|
53
|
+
super
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def view_assigns
|
58
|
+
if env.key? 'motorhead_view_assigns'
|
59
|
+
super.merge env['motorhead_view_assigns']
|
60
|
+
else
|
61
|
+
super
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def render_to_body(options = {})
|
66
|
+
return if (headers['X-Cascade'] == 'pass') && !defined?(@_motorhead_action_successfully_finished)
|
67
|
+
env['motorhead_render_result'] = super
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
AbstractController::Base.prepend Motorhead::AbstractController
|
73
|
+
ActionController::Base.prepend Motorhead::ActionController
|
@@ -0,0 +1,47 @@
|
|
1
|
+
ActionView::Base.class_eval do
|
2
|
+
#FIXME FIXHAML AMCing here because prepending on `render` causes infinite loop when Haml is bundled
|
3
|
+
def render_with_motorhead(options = {}, locals = {}, &block)
|
4
|
+
if (Hash === options) && options.key?(:engine)
|
5
|
+
ext_name = options[:engine][/[^\/]*/]
|
6
|
+
if ext_name.classify.constantize::Engine.active? controller
|
7
|
+
return view_renderer.render(self, options, &block)
|
8
|
+
else
|
9
|
+
return capture(&block)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
render_without_motorhead options, locals, &block
|
13
|
+
end
|
14
|
+
|
15
|
+
alias_method_chain :render, :motorhead
|
16
|
+
end
|
17
|
+
|
18
|
+
module Motorhead
|
19
|
+
module ActionView
|
20
|
+
module Renderer
|
21
|
+
def render(context, options, &block)
|
22
|
+
if options.key? :engine
|
23
|
+
render_engine(context, options, &block)
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def render_engine(context, options, &block)
|
30
|
+
partial_name = options.delete :engine
|
31
|
+
Motorhead::EngineRenderer.new(@lookup_context).render(context, options.merge(partial: partial_name), block)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class EngineRenderer < ::ActionView::PartialRenderer
|
37
|
+
def render(context, options, block)
|
38
|
+
super
|
39
|
+
rescue => e
|
40
|
+
ext_name = options[:partial][/[^\/]*/]
|
41
|
+
(ext_name.classify.constantize::Engine.on_error || Motorhead.config.on_error).call(e)
|
42
|
+
context.capture(&block)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
ActionView::Renderer.prepend Motorhead::ActionView::Renderer
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Motorhead
|
2
|
+
module Engine
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
attr_accessor :on_error
|
7
|
+
|
8
|
+
def active_if(&block)
|
9
|
+
@active_if = block
|
10
|
+
end
|
11
|
+
|
12
|
+
def active?(controller)
|
13
|
+
controller.instance_eval(&@active_if)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
included do
|
18
|
+
isolate_namespace self.parent
|
19
|
+
|
20
|
+
engine_kls = self
|
21
|
+
ActiveSupport.on_load :after_initialize do
|
22
|
+
Rails.application.routes.prepend do
|
23
|
+
mount engine_kls, at: '/'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
data/motorhead.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'motorhead/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "motorhead"
|
8
|
+
spec.version = Motorhead::VERSION
|
9
|
+
spec.authors = ["Akira Matsuda"]
|
10
|
+
spec.email = ["ronnie@dio.jp"]
|
11
|
+
|
12
|
+
spec.summary = 'A safe and rapid prototyping framework for Rails'
|
13
|
+
spec.description = 'Motorhead is a Rails Engine framework that can be used for rapid prototyping, feature toggle, or A/B testing'
|
14
|
+
spec.homepage = 'https://github.com/amatsuda/motorhead'
|
15
|
+
spec.license = "MIT"
|
16
|
+
|
17
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
spec.bindir = "exe"
|
19
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
20
|
+
spec.require_paths = ["lib"]
|
21
|
+
|
22
|
+
spec.add_development_dependency "bundler", "~> 1.10"
|
23
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
24
|
+
spec.add_development_dependency "minitest"
|
25
|
+
spec.add_development_dependency 'rails'
|
26
|
+
spec.add_development_dependency 'sqlite3'
|
27
|
+
spec.add_development_dependency 'capybara'
|
28
|
+
spec.add_development_dependency 'byebug'
|
29
|
+
end
|
metadata
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: motorhead
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Akira Matsuda
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-10-28 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.10'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.10'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '10.0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '10.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: minitest
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: sqlite3
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: capybara
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: byebug
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Motorhead is a Rails Engine framework that can be used for rapid prototyping,
|
112
|
+
feature toggle, or A/B testing
|
113
|
+
email:
|
114
|
+
- ronnie@dio.jp
|
115
|
+
executables: []
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- ".gitignore"
|
120
|
+
- ".travis.yml"
|
121
|
+
- Gemfile
|
122
|
+
- MIT-LICENSE
|
123
|
+
- README.md
|
124
|
+
- Rakefile
|
125
|
+
- bin/console
|
126
|
+
- bin/setup
|
127
|
+
- gemfiles/Gemfile-rails.4.2.x
|
128
|
+
- lib/generators/motorhead/controller_generator.rb
|
129
|
+
- lib/generators/motorhead/templates/controller.rb
|
130
|
+
- lib/generators/motorhead/templates/lib/%name%/engine.rb
|
131
|
+
- lib/generators/motorhead_generator.rb
|
132
|
+
- lib/motorhead.rb
|
133
|
+
- lib/motorhead/abstract_controller.rb
|
134
|
+
- lib/motorhead/action_view.rb
|
135
|
+
- lib/motorhead/config.rb
|
136
|
+
- lib/motorhead/engine.rb
|
137
|
+
- lib/motorhead/version.rb
|
138
|
+
- motorhead.gemspec
|
139
|
+
homepage: https://github.com/amatsuda/motorhead
|
140
|
+
licenses:
|
141
|
+
- MIT
|
142
|
+
metadata: {}
|
143
|
+
post_install_message:
|
144
|
+
rdoc_options: []
|
145
|
+
require_paths:
|
146
|
+
- lib
|
147
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
148
|
+
requirements:
|
149
|
+
- - ">="
|
150
|
+
- !ruby/object:Gem::Version
|
151
|
+
version: '0'
|
152
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
153
|
+
requirements:
|
154
|
+
- - ">="
|
155
|
+
- !ruby/object:Gem::Version
|
156
|
+
version: '0'
|
157
|
+
requirements: []
|
158
|
+
rubyforge_project:
|
159
|
+
rubygems_version: 2.4.5.1
|
160
|
+
signing_key:
|
161
|
+
specification_version: 4
|
162
|
+
summary: A safe and rapid prototyping framework for Rails
|
163
|
+
test_files: []
|