arturo 1.0.0 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -48,7 +48,7 @@ the feature:
48
48
 
49
49
  # in app/controllers/postings_controller:
50
50
  class PostingsController < ApplicationController
51
- require_feature! :live_postings, :only => :recent
51
+ require_feature :live_postings, :only => :recent
52
52
  # ...
53
53
  end
54
54
 
@@ -92,13 +92,17 @@ checkout.
92
92
 
93
93
  ### In Rails
94
94
 
95
- #### Run the migrations:
95
+ #### Run the generators:
96
96
 
97
97
  $ rails g arturo:migration
98
98
  $ rails g arturo:initializer
99
99
  $ rails g arturo:route
100
100
  $ rails g arturo:assets
101
101
 
102
+ #### Run the migration:
103
+
104
+ $ rake db:migrate
105
+
102
106
  #### Edit the configuration
103
107
 
104
108
  ##### Initializer
@@ -106,10 +110,10 @@ checkout.
106
110
  Open up the newly-generated `config/initializers/arturo_initializer.rb`.
107
111
  There are configuration options for the following:
108
112
 
109
- * the block that determines whether a user has permission to manage features
113
+ * the method that determines whether a user has permission to manage features
110
114
  (see [admin permissions](#adminpermissions))
111
- * the block that yields the object that has features
112
- (a User, Person, or Account, see
115
+ * the method that returns the object that has features
116
+ (e.g. User, Person, or Account; see
113
117
  [feature recipients](#featurerecipients))
114
118
  * whitelists and blacklists for features
115
119
  (see [white- and blacklisting](#wblisting))
@@ -132,20 +136,19 @@ work with you on support for your favorite framework.
132
136
 
133
137
  ### <span id='adminpermissions'>Admin Permissions</span>
134
138
 
135
- `Arturo.permit_management` is a block that is run in the context of
136
- a Controller instance. It should return `true` iff the current user
137
- can manage permissions. Configure the block in
138
- `config/initializers/arturo_initializer.rb`. A reasonable implementation
139
- might be
139
+ `Arturo::FeatureManagement#may_manage_features?` is a method that is run in
140
+ the context of a Controller or View instance. It should return `true` if
141
+ and only if the current user may manage permissions. The default implementation
142
+ is as follows:
140
143
 
141
- Arturo.permit_management do
142
- current_user.admin?
143
- end
144
+ current_user.present? && current_user.admin?
144
145
 
145
- or
146
+ You can change the implementation in
147
+ `config/initializers/arturo_initializer.rb`. A reasonable implementation
148
+ might be
146
149
 
147
150
  Arturo.permit_management do
148
- signed_in? && signed_in_person.can?(:manage_features)
151
+ signed_in? && current_user.can?(:manage_features)
149
152
  end
150
153
 
151
154
  ### <span id='featurerecipients'>Feature Recipients</span>
@@ -157,35 +160,23 @@ early days -- may have deployed features on a per-university basis. It wouldn't
157
160
  make much sense to deploy a feature to one user of a Basecamp project but not
158
161
  to others, so 37Signals would probably want a per-project or per-account basis.
159
162
 
160
- `Arturo.feature_recipient` is intended to support these many use cases. It is a
161
- block that returns the current "thing" (a user, account, project, university,
162
- ...) that is a member of the category that is the basis for deploying new
163
- features. Like `Arturo.permit_management`, it is configured in
164
- `config/initializers/arturo_initializer.rb`. It should return an `Object` that
165
- responds to `#id`. If you want to deploy features on a per-user basis, a
166
- reasonable implementation might be
167
-
168
- Arturo.thing_that_has_features do
169
- current_user
170
- end
171
-
172
- or
173
-
174
- Arturo.thing_that_has_features do
175
- signed_in_person
176
- end
163
+ `Arturo::FeatureAvailability#feature_recipient` is intended to support these
164
+ many use cases. It is a method that returns the current "thing" (a user, account,
165
+ project, university, ...) that is a member of the category that is the basis for
166
+ deploying new features. It should return an `Object` that responds to `#id`.
177
167
 
178
- If, on the other hand, you have accounts that have many users and you
179
- want to deploy features on a per-account basis, a reasonable implementation
180
- might be
168
+ The default implementation simply returns `current_user`. Like
169
+ `Arturo::FeatureManagement#may_manage_features?`, this method can be configured
170
+ in `config/initializers/arturo_initializer.rb`. If you want to deploy features
171
+ on a per-account basis, a reasonable implementation might be
181
172
 
182
- Arturo.thing_that_has_features do
173
+ Arturo.feature_recipient do
183
174
  current_account
184
175
  end
185
176
 
186
177
  or
187
178
 
188
- Arturo.thing_that_has_features do
179
+ Arturo.feature_recipient do
189
180
  current_user.account
190
181
  end
191
182
 
@@ -224,10 +215,10 @@ every action within `BookHoldsController` that is invoked by a user who
224
215
  does not have the `:hold_book` feature.
225
216
 
226
217
  class BookHoldsController < ApplicationController
227
- require_feature! :hold_book
218
+ require_feature :hold_book
228
219
  end
229
220
 
230
- `require_feature!` accepts as a second argument a `Hash` that it passes on
221
+ `require_feature` accepts as a second argument a `Hash` that it passes on
231
222
  to `before_filter`, so you can use `:only` and `:except` to specify exactly
232
223
  which actions are filtered.
233
224
 
@@ -258,11 +249,11 @@ The latter can be used like so:
258
249
 
259
250
  **Note**: Arturo does not yet have caching support. Be very careful when
260
251
  caching actions or pages that involve feature detection as you will get
261
- strange behavior when a use who has access to a feature requests a page
252
+ strange behavior when a user who has access to a feature requests a page
262
253
  just after one who does not (and vice versa). The following is the
263
254
  **intended** support for caching.
264
255
 
265
- Both the `require_feature!` before filter and the `if_feature_enabled` block
256
+ Both the `require_feature` before filter and the `if_feature_enabled` block
266
257
  evaluation automatically append a string based on the feature's
267
258
  `last_modified` timestamp to cache keys that Rails generates. Thus, you don't
268
259
  have to worry about expiring caches when you increase a feature's deployment
@@ -272,4 +263,4 @@ percentage. See `Arturo::CacheSupport` for more information.
272
263
 
273
264
  Arturo gets its name from
274
265
  [Professor Maximillian Arturo](http://en.wikipedia.org/wiki/Maximillian_Arturo)
275
- on [Sliders](http://en.wikipedia.org/wiki/Sliders).
266
+ on [Sliders](http://en.wikipedia.org/wiki/Sliders).
@@ -17,6 +17,8 @@ module Arturo
17
17
  # should redefine Arturo::FeaturesController#permitted? to
18
18
  # return true only for users who are permitted to manage features.
19
19
  class FeaturesController < base
20
+ include Arturo::FeatureManagement
21
+
20
22
  unloadable
21
23
  respond_to :html, :json, :xml
22
24
  before_filter :require_permission
@@ -95,7 +97,7 @@ module Arturo
95
97
  protected
96
98
 
97
99
  def require_permission
98
- unless Arturo.permit_management?(self)
100
+ unless may_manage_features?
99
101
  render :action => 'forbidden', :status => 403
100
102
  return false
101
103
  end
@@ -1,8 +1,8 @@
1
1
  module Arturo
2
2
 
3
- require 'arturo/configuration'
4
3
  require 'arturo/special_handling'
5
4
  require 'arturo/feature_availability'
5
+ require 'arturo/feature_management'
6
6
  require 'arturo/controller_filters'
7
7
  require 'arturo/engine' if defined?(Rails) && Rails::VERSION::MAJOR == 3
8
8
 
@@ -18,7 +18,7 @@ module Arturo
18
18
 
19
19
  module ClassMethods
20
20
 
21
- def require_feature!(name, options = {})
21
+ def require_feature(name, options = {})
22
22
  before_filter options do |controller|
23
23
  unless controller.feature_enabled?(name)
24
24
  controller.on_feature_disabled(name)
@@ -4,6 +4,7 @@ module Arturo
4
4
  include Arturo::FeatureAvailability
5
5
  helper Arturo::FeatureAvailability
6
6
  include Arturo::ControllerFilters
7
+ helper Arturo::FeatureManagement
7
8
  end
8
9
  end
9
10
  end
@@ -12,8 +12,7 @@ module Arturo
12
12
  def feature_enabled?(symbol_or_feature)
13
13
  feature = ::Arturo::Feature.to_feature(symbol_or_feature)
14
14
  return false if feature.blank?
15
- thing = ::Arturo.feature_recipient.bind(self).call
16
- feature.enabled_for?(thing)
15
+ feature.enabled_for?(feature_recipient)
17
16
  end
18
17
 
19
18
  def if_feature_enabled(symbol_or_feature, &block)
@@ -24,6 +23,15 @@ module Arturo
24
23
  end
25
24
  end
26
25
 
26
+ # By default, returns current_user.
27
+ #
28
+ # If you would like to change this implementation, it is recommended
29
+ # you do so in config/initializers/arturo_initializer.rb
30
+ # @return [Object] the recipient of features.
31
+ def feature_recipient
32
+ current_user
33
+ end
34
+
27
35
  end
28
36
 
29
37
  end
@@ -0,0 +1,23 @@
1
+ module Arturo
2
+
3
+ # A mixin that is included by Arturo::FeaturesController and is declared
4
+ # as a helper for all views. It provides a single method,
5
+ # may_manage_features?, that returns whether or not the current user
6
+ # may manage features. By default, it is implemented as follows:
7
+ #
8
+ # def may_manage_features?
9
+ # current_user.present? && current_user.admin?
10
+ # end
11
+ #
12
+ # If you would like to change this implementation, it is recommended
13
+ # you do so in config/initializers/arturo_initializer.rb
14
+ module FeatureManagement
15
+
16
+ # @return [true,false] whether the current user may manage features
17
+ def may_manage_features?
18
+ current_user.present? && current_user.admin?
19
+ end
20
+
21
+ end
22
+
23
+ end
@@ -1,21 +1,29 @@
1
1
  require 'arturo'
2
2
 
3
- Arturo.permit_management do
4
- # current_user.present? && current_user.admin?
5
- end
3
+ # Configure who may manage features here.
4
+ # The following is the default implementation.
5
+ # Arturo::FeatureManagement.class_eval do
6
+ # def may_manage_features?
7
+ # current_user.present? && current_user.admin?
8
+ # end
9
+ # end
6
10
 
7
- Arturo.feature_recipient do
8
- # current_user
9
- end
11
+ # Configure what receives features here.
12
+ # The following is the default implementation.
13
+ # Arturo::FeatureAvailability.class_eval do
14
+ # def feature_recipient
15
+ # current_user
16
+ # end
17
+ # end
10
18
 
11
19
  # Whitelists and Blacklists:
12
20
  #
13
- # # Enable feature one for all admins:
14
- # Arturo::Feature.whitelist('feature one') do |user|
21
+ # Enable feature one for all admins:
22
+ # Arturo::Feature.whitelist(:feature_one) do |user|
15
23
  # user.admin?
16
24
  # end
17
25
  #
18
- # # Disable feature two for all small accounts:
19
- # Arturo::Feature.blacklist('feature two') do |user|
26
+ # Disable feature two for all small accounts:
27
+ # Arturo::Feature.blacklist(:feature_two) do |user|
20
28
  # user.account.small?
21
29
  # end
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 1
7
+ - 1
7
8
  - 0
8
- - 0
9
- version: 1.0.0
9
+ version: 1.1.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - James A. Rosen
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-10-24 00:00:00 -07:00
17
+ date: 2010-10-25 00:00:00 -07:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
@@ -108,11 +108,11 @@ extensions: []
108
108
  extra_rdoc_files: []
109
109
 
110
110
  files:
111
- - lib/arturo/configuration.rb
112
111
  - lib/arturo/controller_filters.rb
113
112
  - lib/arturo/engine.rb
114
113
  - lib/arturo/feature_availability.rb
115
114
  - lib/arturo/feature_factories.rb
115
+ - lib/arturo/feature_management.rb
116
116
  - lib/arturo/special_handling.rb
117
117
  - lib/arturo.rb
118
118
  - lib/generators/arturo/assets_generator.rb
@@ -1,43 +0,0 @@
1
- require 'active_support/core_ext/module'
2
-
3
- module Arturo
4
-
5
- # A block that, when bound to a Controller instance, returns
6
- # true iff the current user can manage features.
7
- mattr_writer :permit_management
8
- @@permit_management = lambda { false }
9
-
10
- # A block that, when bound to a Controller or Helper instance,
11
- # returns an object (probably a User, Person, or Account),
12
- # that may or may not have features enabled.
13
- mattr_writer :feature_recipient
14
- @@feature_recipient = lambda { nil }
15
-
16
- # Get or set Arturo's permission block.
17
- # @param [block] block
18
- # @return [block]
19
- # @see Arturo.permission_block
20
- def self.permit_management(&block)
21
- if block
22
- @@permit_management = block
23
- end
24
- @@permit_management
25
- end
26
-
27
- def self.permit_management?(controller)
28
- block = self.permit_management
29
- block && block.call(controller)
30
- end
31
-
32
- # Get or set Arturo's block for retrieving the
33
- # thing that may or may not have features enabled.
34
- # @param [block] block
35
- # @return [block]
36
- def self.feature_recipient(&block)
37
- if block
38
- @@feature_recipient = block
39
- end
40
- @@feature_recipient
41
- end
42
-
43
- end