chanko 1.0.6 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +22 -0
- data/.travis.yml +5 -0
- data/Gemfile +26 -0
- data/MIT-LICENSE +22 -0
- data/README.md +168 -0
- data/Rakefile +12 -0
- data/chanko.gemspec +30 -0
- data/lib/chanko.rb +19 -0
- data/lib/chanko/active_if.rb +59 -0
- data/lib/chanko/config.rb +30 -0
- data/lib/chanko/controller.rb +31 -0
- data/lib/chanko/exception_handler.rb +10 -0
- data/lib/chanko/function.rb +85 -0
- data/lib/chanko/helper.rb +29 -0
- data/lib/chanko/invoker.rb +105 -0
- data/lib/chanko/invoker/function_finder.rb +42 -0
- data/lib/chanko/invoker/options.rb +64 -0
- data/lib/chanko/loader.rb +65 -0
- data/lib/chanko/logger.rb +67 -0
- data/lib/chanko/railtie.rb +11 -0
- data/lib/chanko/test.rb +44 -0
- data/lib/chanko/unit.rb +101 -0
- data/lib/chanko/unit/extender.rb +21 -0
- data/lib/chanko/unit/extender/active_record_class_methods.rb +57 -0
- data/lib/chanko/unit/extender/extension.rb +51 -0
- data/lib/chanko/unit/scope_finder.rb +41 -0
- data/lib/chanko/unit_proxy.rb +30 -0
- data/lib/chanko/unit_proxy_provider.rb +27 -0
- data/lib/chanko/version.rb +3 -0
- data/lib/generators/chanko/unit/templates/unit.rb.erb +84 -0
- data/lib/generators/chanko/unit/unit_generator.rb +49 -0
- data/spec/chanko/controller_spec.rb +44 -0
- data/spec/chanko/exception_handler_spec.rb +39 -0
- data/spec/chanko/function_spec.rb +60 -0
- data/spec/chanko/helper_spec.rb +26 -0
- data/spec/chanko/invoker_spec.rb +156 -0
- data/spec/chanko/loader_spec.rb +43 -0
- data/spec/chanko/logger_spec.rb +94 -0
- data/spec/chanko/test_spec.rb +28 -0
- data/spec/chanko/unit/extender_spec.rb +40 -0
- data/spec/chanko/unit/scope_finder_spec.rb +37 -0
- data/spec/chanko/unit_proxy_provider_spec.rb +68 -0
- data/spec/chanko/unit_proxy_spec.rb +23 -0
- data/spec/chanko/unit_spec.rb +181 -0
- data/spec/controllers/application_controller_spec.rb +15 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +14 -0
- data/spec/dummy/app/assets/stylesheets/main.scss +21 -0
- data/spec/dummy/app/assets/stylesheets/reset.scss +14 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/controllers/entries_controller.rb +33 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/entry.rb +3 -0
- data/spec/dummy/app/units/entry_deletion/entry_deletion.rb +37 -0
- data/spec/dummy/app/units/entry_deletion/views/_delete_link.html.slim +1 -0
- data/spec/dummy/app/views/entries/edit.html.slim +14 -0
- data/spec/dummy/app/views/entries/index.html.slim +5 -0
- data/spec/dummy/app/views/entries/show.html.slim +8 -0
- data/spec/dummy/app/views/layouts/application.html.slim +16 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +68 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +5 -0
- data/spec/dummy/db/migrate/20130127170331_create_entries.rb +11 -0
- data/spec/dummy/db/schema.rb +24 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/fixtures/units/example_unit/example_unit.rb +77 -0
- data/spec/fixtures/units/example_unit/views/_test.html.erb +1 -0
- data/spec/fixtures/units/inactive_unit/inactive_unit.rb +11 -0
- data/spec/fixtures/units/insensitive_unit/insensitive_unit.rb +3 -0
- data/spec/fixtures/units/sensitive_unit/sensitive_unit.rb +4 -0
- data/spec/spec_helper.rb +27 -0
- metadata +339 -170
data/.gitignore
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
log/*.log
|
2
|
+
spec/dummy/db/*.sqlite3
|
3
|
+
spec/dummy/log/*.log
|
4
|
+
spec/dummy/tmp/
|
5
|
+
spec/dummy/.sass-cache
|
6
|
+
*.gem
|
7
|
+
*.rbc
|
8
|
+
.bundle
|
9
|
+
.config
|
10
|
+
.yardoc
|
11
|
+
Gemfile.lock
|
12
|
+
InstalledFiles
|
13
|
+
_yardoc
|
14
|
+
coverage
|
15
|
+
doc/
|
16
|
+
lib/bundler/man
|
17
|
+
pkg
|
18
|
+
rdoc
|
19
|
+
spec/reports
|
20
|
+
test/tmp
|
21
|
+
test/version_tmp
|
22
|
+
tmp
|
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
source "https://rubygems.org"
|
2
|
+
|
3
|
+
gemspec
|
4
|
+
|
5
|
+
group :development, :test, :production do
|
6
|
+
gem "jquery-rails"
|
7
|
+
gem "quiet_assets"
|
8
|
+
gem "rails", ">= 3.0.10"
|
9
|
+
gem "slim"
|
10
|
+
gem "sqlite3"
|
11
|
+
end
|
12
|
+
|
13
|
+
group :test do
|
14
|
+
gem "rspec-rails", "2.12.2"
|
15
|
+
end
|
16
|
+
|
17
|
+
group :development, :test do
|
18
|
+
gem "pry-rails"
|
19
|
+
gem "thin"
|
20
|
+
end
|
21
|
+
|
22
|
+
group :assets do
|
23
|
+
gem "sass-rails", ">= 3.0.10"
|
24
|
+
gem "coffee-rails", ">= 3.0.10"
|
25
|
+
gem "uglifier"
|
26
|
+
end
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2013 Ryo Nakamura
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,168 @@
|
|
1
|
+
# Chanko
|
2
|
+
Chanko provides a simple framework for rapidly and safely prototyping new
|
3
|
+
features in your production Rails app, and exposing these prototypes to
|
4
|
+
specified segments of your user base.
|
5
|
+
|
6
|
+
With Chanko, you can release many concurrent features and independently manage
|
7
|
+
which users see them. If there are errors with any chanko, it will be
|
8
|
+
automatically removed, without impacting your site.
|
9
|
+
|
10
|
+
|
11
|
+
## Requirements
|
12
|
+
* Ruby >= 1.8.7
|
13
|
+
* Rails >= 3.0.10
|
14
|
+
|
15
|
+
|
16
|
+
## Usage
|
17
|
+
Add to your Gemfile.
|
18
|
+
|
19
|
+
```ruby
|
20
|
+
gem "chanko"
|
21
|
+
```
|
22
|
+
|
23
|
+
## Files
|
24
|
+
Chanko provides a generator to create a template of unit.
|
25
|
+
|
26
|
+
```
|
27
|
+
$ rails generate chanko:install example_unit
|
28
|
+
```
|
29
|
+
|
30
|
+
## Invoke
|
31
|
+
You can invoke the logics defined in your units via `invoke` and `unit` methods.
|
32
|
+
In controller class context, `unit_action` utility is also provided.
|
33
|
+
The block passed to `invoke` is a fallback executed if any problem occurs in invoking.
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
# app/controllers/users_controller.rb
|
37
|
+
class UsersController < ApplicationController
|
38
|
+
unit_action :example_unit, :show
|
39
|
+
|
40
|
+
def index
|
41
|
+
invoke(:example_unit, :index) do
|
42
|
+
@users = User.all
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
```
|
47
|
+
|
48
|
+
```
|
49
|
+
-# app/views/examples/index.html.slim
|
50
|
+
= unit.helper_method
|
51
|
+
= invoke(:example_unit, :render_example)
|
52
|
+
```
|
53
|
+
|
54
|
+
```
|
55
|
+
-# app/units/example_unit/views/_example.html.slim
|
56
|
+
= foo
|
57
|
+
```
|
58
|
+
|
59
|
+
## Unit
|
60
|
+
|
61
|
+
### module
|
62
|
+
You can define your MVC code here.
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
# app/units/example_unit/example_unit.rb
|
66
|
+
module ExampleUnit
|
67
|
+
include Chanko::Unit
|
68
|
+
...
|
69
|
+
end
|
70
|
+
```
|
71
|
+
|
72
|
+
### active_if
|
73
|
+
This block is used to decide if this unit is active or not.
|
74
|
+
`context` is the receiver object of `invoke`.
|
75
|
+
`options` is passed via `invoke(:foo, :bar, :active_if_options => { ... })`.
|
76
|
+
By default, this is set as `active_if { true }`.
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
active_if do |context, options|
|
80
|
+
true
|
81
|
+
end
|
82
|
+
```
|
83
|
+
|
84
|
+
### raise_error
|
85
|
+
By default, any error raised in production env is ignored.
|
86
|
+
`raise_error` is used to force an unit to raise up errors occured in invoking.
|
87
|
+
You can force all units to raise up errors by `Config.raise_error = true`.
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
raise_error
|
91
|
+
```
|
92
|
+
|
93
|
+
### function
|
94
|
+
In controller or view context, you can call functions defined by `function`
|
95
|
+
via `invoke(:example_unit, :function_name)`.
|
96
|
+
|
97
|
+
```ruby
|
98
|
+
scope(:controller) do
|
99
|
+
function(:show) do
|
100
|
+
@user = User.find(params[:id])
|
101
|
+
end
|
102
|
+
|
103
|
+
function(:index) do
|
104
|
+
@users = User.active
|
105
|
+
end
|
106
|
+
end
|
107
|
+
```
|
108
|
+
|
109
|
+
### render
|
110
|
+
The view path app/units/example_unit/views is added into view_paths in invoking.
|
111
|
+
So you can render app/units/example_unit/views/_example.html.slim in invoking.
|
112
|
+
|
113
|
+
```ruby
|
114
|
+
scope(:view) do
|
115
|
+
function(:render_example) do
|
116
|
+
render "/example", :foo => hello("world")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
```
|
120
|
+
|
121
|
+
### models
|
122
|
+
In models block, you can expand model features by `expand` method.
|
123
|
+
The expanded methods are available via unit proxy like `User.unit.active`,
|
124
|
+
and `User.find(params[:id]).unit.active?`, and so on.
|
125
|
+
|
126
|
+
```ruby
|
127
|
+
models do
|
128
|
+
expand(:User) do
|
129
|
+
scope :active, lambda { where(:deleted_at => nil) }
|
130
|
+
|
131
|
+
def active?
|
132
|
+
deleted_at.nil?
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
```
|
137
|
+
|
138
|
+
### shared
|
139
|
+
You can call methods defined by `shared` in invoking.
|
140
|
+
|
141
|
+
```ruby
|
142
|
+
shared(:hello) do |world|
|
143
|
+
"Hello, #{world}"
|
144
|
+
end
|
145
|
+
```
|
146
|
+
|
147
|
+
### helpers
|
148
|
+
You can call helpers in view via unit proxy like `unit.helper_method`.
|
149
|
+
|
150
|
+
```ruby
|
151
|
+
helpers do
|
152
|
+
def helper_method
|
153
|
+
"helper method"
|
154
|
+
end
|
155
|
+
end
|
156
|
+
```
|
157
|
+
|
158
|
+
|
159
|
+
## Example
|
160
|
+
https://github.com/cookpad/chanko/tree/master/spec/dummy
|
161
|
+
Chanko provides an example rails application in spec/dummy directory.
|
162
|
+
|
163
|
+
```
|
164
|
+
$ git clone git@github.com:cookpad/chanko.git
|
165
|
+
$ cd chanko/spec/dummy
|
166
|
+
$ rails s
|
167
|
+
$ open http://localhost:3000
|
168
|
+
```
|
data/Rakefile
ADDED
data/chanko.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
lib = File.expand_path("../lib", __FILE__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "chanko/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |gem|
|
6
|
+
gem.name = "chanko"
|
7
|
+
gem.version = Chanko::VERSION
|
8
|
+
gem.authors = ["Ryo Nakamura"]
|
9
|
+
gem.email = ["r7kamura@gmail.com"]
|
10
|
+
gem.description = "Chanko is a Rails extension tool"
|
11
|
+
gem.summary = "Rails extension tool"
|
12
|
+
gem.homepage = "https://github.com/cookpad/chanko"
|
13
|
+
|
14
|
+
gem.files = `git ls-files`.split($/)
|
15
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
16
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
17
|
+
gem.require_paths = ["lib"]
|
18
|
+
|
19
|
+
gem.add_dependency "rails", ">= 3.0.10"
|
20
|
+
gem.add_development_dependency "coffee-rails", ">= 3.0.10"
|
21
|
+
gem.add_development_dependency "jquery-rails"
|
22
|
+
gem.add_development_dependency "pry"
|
23
|
+
gem.add_development_dependency "rspec-rails", "2.12.2"
|
24
|
+
gem.add_development_dependency "sass-rails", ">= 3.0.10"
|
25
|
+
gem.add_development_dependency "simplecov"
|
26
|
+
gem.add_development_dependency "slim"
|
27
|
+
gem.add_development_dependency "sqlite3"
|
28
|
+
gem.add_development_dependency "thin"
|
29
|
+
gem.add_development_dependency "uglifier"
|
30
|
+
end
|
data/lib/chanko.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
require "action_controller"
|
2
|
+
require "action_view"
|
3
|
+
require "active_record"
|
4
|
+
require "active_support/all"
|
5
|
+
require "rails"
|
6
|
+
|
7
|
+
require "chanko/active_if"
|
8
|
+
require "chanko/config"
|
9
|
+
require "chanko/controller"
|
10
|
+
require "chanko/exception_handler"
|
11
|
+
require "chanko/function"
|
12
|
+
require "chanko/helper"
|
13
|
+
require "chanko/invoker"
|
14
|
+
require "chanko/loader"
|
15
|
+
require "chanko/logger"
|
16
|
+
require "chanko/railtie"
|
17
|
+
require "chanko/unit"
|
18
|
+
require "chanko/unit_proxy"
|
19
|
+
require "chanko/unit_proxy_provider"
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Chanko
|
2
|
+
class ActiveIf
|
3
|
+
class << self
|
4
|
+
def define(label, &block)
|
5
|
+
definitions[label] = block
|
6
|
+
end
|
7
|
+
|
8
|
+
def find(label)
|
9
|
+
definitions[label]
|
10
|
+
end
|
11
|
+
|
12
|
+
def definitions
|
13
|
+
@definitions ||= {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def clear
|
17
|
+
definitions.clear
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
attr_reader :conditions, :options
|
22
|
+
|
23
|
+
def initialize(*conditions, &block)
|
24
|
+
@options = conditions.extract_options!
|
25
|
+
@conditions = conditions
|
26
|
+
@block = block
|
27
|
+
end
|
28
|
+
|
29
|
+
def active?(context, options = {})
|
30
|
+
blocks.all? {|block| block.call(context, options) }
|
31
|
+
end
|
32
|
+
|
33
|
+
def blocks
|
34
|
+
@blocks ||= begin
|
35
|
+
conditions.map do |condition|
|
36
|
+
condition.is_a?(Any) ? condition.to_block : self.class.find(condition)
|
37
|
+
end << @block
|
38
|
+
end.compact
|
39
|
+
end
|
40
|
+
|
41
|
+
class Any
|
42
|
+
def initialize(*labels)
|
43
|
+
@labels = labels
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_block
|
47
|
+
proc do |context, options|
|
48
|
+
definitions.any? do |definition|
|
49
|
+
definition.call(context, options)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def definitions
|
55
|
+
@labels.map {|label| ActiveIf.find(label) }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Chanko
|
2
|
+
module Config
|
3
|
+
class << self
|
4
|
+
attr_accessor(
|
5
|
+
:auto_reload,
|
6
|
+
:backtrace_limit,
|
7
|
+
:cache_units,
|
8
|
+
:compatible_css_class,
|
9
|
+
:enable_logger,
|
10
|
+
:proxy_method_name,
|
11
|
+
:raise_error,
|
12
|
+
:resolver,
|
13
|
+
:units_directory_path
|
14
|
+
)
|
15
|
+
|
16
|
+
def reset
|
17
|
+
self.auto_reload = Rails.env.development? || Rails.env.test?
|
18
|
+
self.backtrace_limit = 10
|
19
|
+
self.compatible_css_class = false
|
20
|
+
self.enable_logger = true
|
21
|
+
self.proxy_method_name = :unit
|
22
|
+
self.raise_error = Rails.env.development?
|
23
|
+
self.resolver = ActionView::OptimizedFileSystemResolver
|
24
|
+
self.units_directory_path = "app/units"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
reset
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Chanko
|
2
|
+
module Controller
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
private
|
7
|
+
|
8
|
+
def inherited(base)
|
9
|
+
if Config.auto_reload && base.name == "ApplicationController"
|
10
|
+
base.class_eval do
|
11
|
+
prepend_before_filter do
|
12
|
+
Chanko::Loader.cache.clear
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def unit_action(unit_name, *function_names, &block)
|
20
|
+
options = function_names.extract_options!
|
21
|
+
block ||= Proc.new { head 400 }
|
22
|
+
Array.wrap(function_names).each do |function_name|
|
23
|
+
define_method(function_name) do
|
24
|
+
invoke(unit_name, function_name, options, &block)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
alias_method :ext_action, :unit_action
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|