arturo 1.0.0 → 1.1.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.
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