Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 272 lines (224 sloc) 8.328 kb
4e9ee55 @eudoxa public release
eudoxa authored
1 = Chanko
2 == What is Chanko
a644b88 @tapster minor tweaks to intro
tapster authored
3 Chanko provides a simple framework for rapidly and safely prototyping new
4 features in your production Rails app, and exposing these prototypes to
5 specified segments of your user base.
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
6
7 With Chanko, you can release many concurrent features and independently manage
8 which users see them. If there are errors with any chanko, it will be
9 automatially removed, without impacting your site.
10
a644b88 @tapster minor tweaks to intro
tapster authored
11 Please take a look at https://github.com/cookpad/chanko_sample which is a
12 simple example app using chanko.
13
14 Chanko is currently released as a beta.
4e9ee55 @eudoxa public release
eudoxa authored
15
16 == Supported versions
17 Ruby 1.8.7, 1.9.2
d5208c2 @eudoxa Update README.rdoc
eudoxa authored
18
4e9ee55 @eudoxa public release
eudoxa authored
19 Rails 3.0.10 ~
d5208c2 @eudoxa Update README.rdoc
eudoxa authored
20
4e9ee55 @eudoxa public release
eudoxa authored
21 == Install
22 Add your Gemfile.
3b18466 @tricknotes fixed README
tricknotes authored
23 gem 'chanko', :git => 'git://github.com/cookpad/chanko.git'
4e9ee55 @eudoxa public release
eudoxa authored
24 Run install.
25 rails generate chanko:install
26 Add this code to ApplicationHelper.
27 include Chanko::Invoker
1efe5c2 @eudoxa Update README
eudoxa authored
28 include Chanko::Helper
4e9ee55 @eudoxa public release
eudoxa authored
29
30 == Files
31
32 Generate chanko.
33 rails generate chanko sample
f47e3ae @eudoxa refactor class and method name
eudoxa authored
34 create app/units/sample/sample.rb
35 create app/units/sample/views/_show.html.haml
36 create app/units/sample/stylesheets/tutorial.scss
37 create app/units/sample/images/logo.png
38 create app/units/sample/specs/models/sample_spec.rb
39 create app/units/sample/specs/controllers/sample_controller_spec.rb
40 create app/units/sample/specs/helpers/sample_helper_spec.rb
41
42 === app/units/sample/sample.rb
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
43 Main file. You write your model and controller logic in this file.
4e9ee55 @eudoxa public release
eudoxa authored
44
f47e3ae @eudoxa refactor class and method name
eudoxa authored
45 === app/units/sample/views
4e9ee55 @eudoxa public release
eudoxa authored
46 The view files for your chanko. Each chanko refers to its own views directory.
47
f47e3ae @eudoxa refactor class and method name
eudoxa authored
48 === app/units/sample/stylesheets/tutorial.scss
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
49 Write styles for your chanko in this file. These files will be merged during
50 startup or first access.
4e9ee55 @eudoxa public release
eudoxa authored
51
f47e3ae @eudoxa refactor class and method name
eudoxa authored
52 === app/units/sample/images/logo.png
4e9ee55 @eudoxa public release
eudoxa authored
53 The image files for this chanko.
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
54 if you manually created this directory, you should create a symbolic link from
f47e3ae @eudoxa refactor class and method name
eudoxa authored
55 app/units/sample/images to (public or assets)/images/units/#{unit_name}
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
56 with attention to use the relative path.
4e9ee55 @eudoxa public release
eudoxa authored
57 If you used generator, the symbolic link is automaticlly generated.
58
f47e3ae @eudoxa refactor class and method name
eudoxa authored
59 === app/units/sample/specs/
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
60 Tests for this chanko go here.
4e9ee55 @eudoxa public release
eudoxa authored
61
62 == Syntax
63 module Sample
64 include Chanko::Unit
65
66 # active_if's block is used to decide if the chanko is active or not.
f47e3ae @eudoxa refactor class and method name
eudoxa authored
67 # context is the object which invoked the function.
4e9ee55 @eudoxa public release
eudoxa authored
68 active_if :always_true do |context, options|
69 true
70 end
71
72 shared(:hello) do |name|
73 "hello #{name}"
74 end
75
76 scope(:controller) do
f47e3ae @eudoxa refactor class and method name
eudoxa authored
77 function(:controller_show) do
4e9ee55 @eudoxa public release
eudoxa authored
78 # controller code here
79 end
80 end
81
82 scope(:view) do
f47e3ae @eudoxa refactor class and method name
eudoxa authored
83 function(:view_show) do
4e9ee55 @eudoxa public release
eudoxa authored
84 render :partial => "/show"
85 end
86 end
87
88 models do
89 expand("ExpandedModel") do
a871c99 @eudoxa update README
eudoxa authored
90 #expanded_model.ext(:sample).has_many_associations
4e9ee55 @eudoxa public release
eudoxa authored
91 has_many :has_many_associations
92 has_one :has_one_association
1efe5c2 @eudoxa Update README
eudoxa authored
93
94 # should use lambda
95 scope :exists, lambda { where(:deleted_at => nil) }
4e9ee55 @eudoxa public release
eudoxa authored
96
a871c99 @eudoxa update README
eudoxa authored
97 # expanded_model_instance.ext.new_method
4e9ee55 @eudoxa public release
eudoxa authored
98 def new_method
99 end
100
a871c99 @eudoxa update README
eudoxa authored
101 #expanded_mode.ext.new_method
4e9ee55 @eudoxa public release
eudoxa authored
102 class_methods do
103 def new_class_method
104 end
105 end
106 end
107 end
108
109 helpers do
a871c99 @eudoxa update README
eudoxa authored
110 # ext.helper_method
4e9ee55 @eudoxa public release
eudoxa authored
111 def helper_method
112 end
113 end
114 end
115
116 == active_if
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
117 "active_if()" decides if the chanko is enabled or not. active_if receives an
118 arg of the invoked context, such as the controller.
4e9ee55 @eudoxa public release
eudoxa authored
119 The chanko is enabled when the block returns true.
120 # activeif's block is used to decide if the chanko is active or not.
f47e3ae @eudoxa refactor class and method name
eudoxa authored
121 # context is the object which invoked the function.
122 which invoking function object.
4e9ee55 @eudoxa public release
eudoxa authored
123 active_if do |context, options|
124 true
125 end
126
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
127 Also, "active_if()" accepts pre defined symbols. "active_if()" evaluates the AND
128 result for all symbols and the block.
4e9ee55 @eudoxa public release
eudoxa authored
129 # This definition means "user is staff and environment is not production"
130 active_if :staff, :not_production do |context, options|
131 # some additional conditions
132 end
133
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
134 You can define additional symbols in lib/active_if_files/main.rb.
4e9ee55 @eudoxa public release
eudoxa authored
135 Chanko::ActiveIf.define(:not_production?) do |context, options|
136 !Rails.env.production?
137 end
138
139 Chanko::ActiveIf.define(:staff) do |context, options|
140 user = options[:user] || context.instance_variable_get('@login_user')
141 next false unless user
142 next false unless user.staff?
143 next true
144 end
145
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
146 When you want to use an OR condition, use "any()".
4e9ee55 @eudoxa public release
eudoxa authored
147 # This means "current user is staff or paid user. And environment is not production"
148 active_if any(:staff, :paid), :not_production
149
150 == shared method
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
151 "shared()" is the syntax for shared method definitions. you can use the defined
f47e3ae @eudoxa refactor class and method name
eudoxa authored
152 method through functions of either :controller or :view. A block of a shared
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
153 method behaves as an instance method.
4e9ee55 @eudoxa public release
eudoxa authored
154 shared(:hello) do |name|
155 "hello #{name}"
156 end
157
158 scope(:view) do
f47e3ae @eudoxa refactor class and method name
eudoxa authored
159 function(:hello) do
4e9ee55 @eudoxa public release
eudoxa authored
160 hello("alice")
161 end
162 end
163
f47e3ae @eudoxa refactor class and method name
eudoxa authored
164 == function
165 A "function()" is expanded in the calling code. This block's context behaves
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
166 as an invoked context, so you can access the original context's instance
f47e3ae @eudoxa refactor class and method name
eudoxa authored
167 variables. if you need to access local variables, a function provides a :locals
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
168 option that is similar to :locals use in render.
f47e3ae @eudoxa refactor class and method name
eudoxa authored
169 A function is scoped, and its scope is a restriction for the function. The
170 function is only called from scoped context.
4e9ee55 @eudoxa public release
eudoxa authored
171 #scope can receive specified context such as "scope('UsersController')".
172 scope(:controller) do
f47e3ae @eudoxa refactor class and method name
eudoxa authored
173 function(:controller_show) do
4e9ee55 @eudoxa public release
eudoxa authored
174 # controller code here
175 end
176 end
177
f47e3ae @eudoxa refactor class and method name
eudoxa authored
178 "invoke()" in your controller runs a function block if the active_if block
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
179 returns true. In this case, if active_if for the sample chanko is true, then
180 controller_show will be invoked in the chanko main.rb
4e9ee55 @eudoxa public release
eudoxa authored
181 class UsersController
182 def show
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
183 invoke(:sample, :controller_show)
4e9ee55 @eudoxa public release
eudoxa authored
184 end
185 end
186
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
187 "invoke()" can receive a block as a default fallback. The block is executed if
f47e3ae @eudoxa refactor class and method name
eudoxa authored
188 the active_if block returns false or the function raises an error.
806d8ff @eudoxa fix incorrect document
eudoxa authored
189 invoke(:sample, :controller_show) do
4e9ee55 @eudoxa public release
eudoxa authored
190 default_behaviour
191 end
192
193 "run_default()" method runs default block and return a result as string.
f47e3ae @eudoxa refactor class and method name
eudoxa authored
194 it is used by function block
195 function(:hello) do
4e9ee55 @eudoxa public release
eudoxa authored
196 result = run_default
197 "#{result} + hello"
198 end
199
f47e3ae @eudoxa refactor class and method name
eudoxa authored
200 "invoke()" can receive multiple functions. "invoke" tries to run the functions
201 in turn. Only the first enabled function is executed.
202 #invoke doesn't run second_unit function if first_unit is enabled.
203 invoke([:first_unit, :show], [:second_unit, :show])
4e9ee55 @eudoxa public release
eudoxa authored
204
205 "invoke"() doesn't run if the specified chanko in the :if is disabled
f47e3ae @eudoxa refactor class and method name
eudoxa authored
206 invoke(:sample, :show, :if => :depend_on_unit)
4e9ee55 @eudoxa public release
eudoxa authored
207
208 == expand
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
209 "expand()" expands existing model methods and adds chanko helper methods. The
210 expanded method is only used by the expanding chanko.
a871c99 @eudoxa update README
eudoxa authored
211 All expanded method must be used in your code via *ext* proxy as below.
212 user_instance.ext.expanded_method
4e9ee55 @eudoxa public release
eudoxa authored
213
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
214 You can write expanding methods for current models. The "models()" block
215 provides association and named_scope and class method syntax.
4e9ee55 @eudoxa public release
eudoxa authored
216 models do
217 expand("ExpandedModel") do
a871c99 @eudoxa update README
eudoxa authored
218 #expanded_model.ext.has_many_associations
4e9ee55 @eudoxa public release
eudoxa authored
219 has_many :has_many_associations
220 has_one :has_one_association
221 has_many :through_associations, :through => label(:has_many_associations)
222 named_scope :exists, :conditions => {:deleted_at => nil}
a871c99 @eudoxa update README
eudoxa authored
223 # expanded_model_instance.ext.new_method
4e9ee55 @eudoxa public release
eudoxa authored
224 def new_method
225 end
226
a871c99 @eudoxa update README
eudoxa authored
227 #expanded_mode.ext.new_method
4e9ee55 @eudoxa public release
eudoxa authored
228 class_methods do
229 def cmethod
230 end
231 end
232 end
233 end
234
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
235 When used as a symbol as an :include option for ActiveRecord, you must wrap
a871c99 @eudoxa update README
eudoxa authored
236 label with "ext.label()" syntax.
237 User.find(:first, :include => [ext.label(:recipes)])
4e9ee55 @eudoxa public release
eudoxa authored
238
239 == Helpers
240 You can write chanko helpers.
241 helpers do
242 def helper_method
243 end
244 end
245
a871c99 @eudoxa update README
eudoxa authored
246 And can use helpers in views and controllers via *ext* proxy.
247 function(:sample) { ext.hello }
4e9ee55 @eudoxa public release
eudoxa authored
248 helpers { def hello; 'hello'; end }
249
250 == Tips
251 return from inside of invoke block.
252 Use following code.
253 invoke(:hoge, :aaa) do
254 redirect_to xxx
255 end
256 return if performed?
257
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
258 always activate or deactivate a chanko.
4e9ee55 @eudoxa public release
eudoxa authored
259 Use :always_true/:always_false on active_if.
260 active_if :always_true # or :always_false
261
262 invoke with before_filter.
263 Use block and invoke.
264 before_filter :only => :index do |controller|
f47e3ae @eudoxa refactor class and method name
eudoxa authored
265 controller.invoke(:your_unit, :before_function)
4e9ee55 @eudoxa public release
eudoxa authored
266 end
267
f84abf1 @tapster expand the description and clean up some of the english in the docs
tapster authored
268 check status of a chanko.
4e9ee55 @eudoxa public release
eudoxa authored
269 you can check the status of an chanko. In almost all situations, context is controller.(deprecated ?)
a871c99 @eudoxa update README
eudoxa authored
270 ext(:sample).active? #=> return boolean
4e9ee55 @eudoxa public release
eudoxa authored
271
Something went wrong with that request. Please try again.