chanko 1.0.6 → 2.0.0

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.
Files changed (95) hide show
  1. data/.gitignore +22 -0
  2. data/.travis.yml +5 -0
  3. data/Gemfile +26 -0
  4. data/MIT-LICENSE +22 -0
  5. data/README.md +168 -0
  6. data/Rakefile +12 -0
  7. data/chanko.gemspec +30 -0
  8. data/lib/chanko.rb +19 -0
  9. data/lib/chanko/active_if.rb +59 -0
  10. data/lib/chanko/config.rb +30 -0
  11. data/lib/chanko/controller.rb +31 -0
  12. data/lib/chanko/exception_handler.rb +10 -0
  13. data/lib/chanko/function.rb +85 -0
  14. data/lib/chanko/helper.rb +29 -0
  15. data/lib/chanko/invoker.rb +105 -0
  16. data/lib/chanko/invoker/function_finder.rb +42 -0
  17. data/lib/chanko/invoker/options.rb +64 -0
  18. data/lib/chanko/loader.rb +65 -0
  19. data/lib/chanko/logger.rb +67 -0
  20. data/lib/chanko/railtie.rb +11 -0
  21. data/lib/chanko/test.rb +44 -0
  22. data/lib/chanko/unit.rb +101 -0
  23. data/lib/chanko/unit/extender.rb +21 -0
  24. data/lib/chanko/unit/extender/active_record_class_methods.rb +57 -0
  25. data/lib/chanko/unit/extender/extension.rb +51 -0
  26. data/lib/chanko/unit/scope_finder.rb +41 -0
  27. data/lib/chanko/unit_proxy.rb +30 -0
  28. data/lib/chanko/unit_proxy_provider.rb +27 -0
  29. data/lib/chanko/version.rb +3 -0
  30. data/lib/generators/chanko/unit/templates/unit.rb.erb +84 -0
  31. data/lib/generators/chanko/unit/unit_generator.rb +49 -0
  32. data/spec/chanko/controller_spec.rb +44 -0
  33. data/spec/chanko/exception_handler_spec.rb +39 -0
  34. data/spec/chanko/function_spec.rb +60 -0
  35. data/spec/chanko/helper_spec.rb +26 -0
  36. data/spec/chanko/invoker_spec.rb +156 -0
  37. data/spec/chanko/loader_spec.rb +43 -0
  38. data/spec/chanko/logger_spec.rb +94 -0
  39. data/spec/chanko/test_spec.rb +28 -0
  40. data/spec/chanko/unit/extender_spec.rb +40 -0
  41. data/spec/chanko/unit/scope_finder_spec.rb +37 -0
  42. data/spec/chanko/unit_proxy_provider_spec.rb +68 -0
  43. data/spec/chanko/unit_proxy_spec.rb +23 -0
  44. data/spec/chanko/unit_spec.rb +181 -0
  45. data/spec/controllers/application_controller_spec.rb +15 -0
  46. data/spec/dummy/README.rdoc +261 -0
  47. data/spec/dummy/Rakefile +7 -0
  48. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  49. data/spec/dummy/app/assets/stylesheets/application.css +14 -0
  50. data/spec/dummy/app/assets/stylesheets/main.scss +21 -0
  51. data/spec/dummy/app/assets/stylesheets/reset.scss +14 -0
  52. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  53. data/spec/dummy/app/controllers/entries_controller.rb +33 -0
  54. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  55. data/spec/dummy/app/mailers/.gitkeep +0 -0
  56. data/spec/dummy/app/models/.gitkeep +0 -0
  57. data/spec/dummy/app/models/entry.rb +3 -0
  58. data/spec/dummy/app/units/entry_deletion/entry_deletion.rb +37 -0
  59. data/spec/dummy/app/units/entry_deletion/views/_delete_link.html.slim +1 -0
  60. data/spec/dummy/app/views/entries/edit.html.slim +14 -0
  61. data/spec/dummy/app/views/entries/index.html.slim +5 -0
  62. data/spec/dummy/app/views/entries/show.html.slim +8 -0
  63. data/spec/dummy/app/views/layouts/application.html.slim +16 -0
  64. data/spec/dummy/config.ru +4 -0
  65. data/spec/dummy/config/application.rb +68 -0
  66. data/spec/dummy/config/boot.rb +10 -0
  67. data/spec/dummy/config/database.yml +25 -0
  68. data/spec/dummy/config/environment.rb +5 -0
  69. data/spec/dummy/config/environments/development.rb +37 -0
  70. data/spec/dummy/config/environments/production.rb +67 -0
  71. data/spec/dummy/config/environments/test.rb +37 -0
  72. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  73. data/spec/dummy/config/initializers/inflections.rb +15 -0
  74. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  75. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  76. data/spec/dummy/config/initializers/session_store.rb +8 -0
  77. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  78. data/spec/dummy/config/locales/en.yml +5 -0
  79. data/spec/dummy/config/routes.rb +5 -0
  80. data/spec/dummy/db/migrate/20130127170331_create_entries.rb +11 -0
  81. data/spec/dummy/db/schema.rb +24 -0
  82. data/spec/dummy/lib/assets/.gitkeep +0 -0
  83. data/spec/dummy/log/.gitkeep +0 -0
  84. data/spec/dummy/public/404.html +26 -0
  85. data/spec/dummy/public/422.html +26 -0
  86. data/spec/dummy/public/500.html +25 -0
  87. data/spec/dummy/public/favicon.ico +0 -0
  88. data/spec/dummy/script/rails +6 -0
  89. data/spec/fixtures/units/example_unit/example_unit.rb +77 -0
  90. data/spec/fixtures/units/example_unit/views/_test.html.erb +1 -0
  91. data/spec/fixtures/units/inactive_unit/inactive_unit.rb +11 -0
  92. data/spec/fixtures/units/insensitive_unit/insensitive_unit.rb +3 -0
  93. data/spec/fixtures/units/sensitive_unit/sensitive_unit.rb +4 -0
  94. data/spec/spec_helper.rb +27 -0
  95. metadata +339 -170
@@ -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
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
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
@@ -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.
@@ -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
+ ```
@@ -0,0 +1,12 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ begin
4
+ require "rspec/core/rake_task"
5
+ RSpec::Core::RakeTask.new(:spec) do |spec|
6
+ spec.pattern = "spec/**/*_spec.rb"
7
+ spec.rspec_opts = ["-cfs"]
8
+ end
9
+ rescue LoadError => e
10
+ end
11
+
12
+ task :default => :spec
@@ -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
@@ -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
@@ -0,0 +1,10 @@
1
+ module Chanko
2
+ module ExceptionHandler
3
+ class << self
4
+ def handle(exception, unit = nil)
5
+ Logger.debug(exception)
6
+ raise exception if unit.try(:raise_error?) || Config.raise_error
7
+ end
8
+ end
9
+ end
10
+ end