mass_assignment 1.0.0 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -8,17 +8,22 @@ h3. What It Is
8
8
 
9
9
  A robust mass assignment method with a small and obvious syntax.
10
10
 
11
+ h4. The Traditional Approach
12
+
11
13
  The normal mass assignment protection comes from attr_protected and attr_accessible. There are a few problems with this approach:
12
14
 
13
- * Often never implemented, leaving a wide-open system. And once implemented, easy to forget when adding new attributes, leading to bugs (in an attr_accessible system) or security holes (in an attr_protected system).
14
- * Restricts coding syntax. You can't easily use update_attributes() or attributes= because your whitelist/blacklist gets in your own way.
15
- * Not contextual. The list of allowed attributes can't change to accomodate different user permissions or situations.
15
+ * *Often never implemented*, leaving a wide-open system. Rails blogs are full of dire warnings about forgetting your attr_protected.
16
+ * Once implemented, *easy to forget* when adding new attributes, leading to *bugs* (in an attr_accessible system) or *security holes* (in an attr_protected system).
17
+ * Restricts coding syntax. You can't easily use update_attributes() or attributes= because *your whitelist/blacklist gets in your own way*.
18
+ * Not contextual. The *list of allowed attributes can't change* to accomodate different user permissions or situations.
19
+
20
+ h4. The MassAssignment Approach
16
21
 
17
- This plugin's solution is to let you specify an obvious list of allowed attributes when you mass assign attributes.
22
+ This plugin's solution is to let you specify an obvious and explicit list of allowed attributes when you mass assign attributes.
18
23
 
19
- * The list of allowed attributes is in your controller at calltime, so it's easier to remember and update (it's not a hidden, magical system).
20
- * The list of allowed attributes is optional, so it doesn't get in your way.
21
- * Your controller can easily enforce permissions by evaluating the current user (Admin Controller) or the current situation (creates vs updates).
24
+ * The list of allowed attributes is in your controller at calltime, so it's *easier to remember and update* (it's not a hidden, magical system).
25
+ * The list of allowed attributes is optional, so it *doesn't get in your way*. You can use update_attributes() and attributes= for your own code again.
26
+ * Assignment *permissions are enforced by the controller*, where permissions belong. You can evaluate the current user or current situation and write the whitelist on the fly.
22
27
 
23
28
  And as a bonus, permission plugins have a much easier time of things. The list of allowed attributes may be pulled from a permissions table without any awkward User.current class or thread variables.
24
29
 
@@ -40,20 +45,11 @@ Let's take a very plausible situation where you would want three separate lists
40
45
 
41
46
  def update
42
47
  @user = User.find(params[:id])
43
- # username is no longer accepted later
44
- @user.assign(params[:user], [:email, :password, :password_confirmation])
45
- @user.save!
46
- ...
47
- end
48
- end
49
-
50
- class Admin::UsersController < ApplicationController
51
- before_filter :admin_required
52
-
53
- def update
54
- @user = User.find(params[:id])
55
- # admins, on the other hand, may change the username as needed, but may not set passwords
56
- @user.assign(:params[:user], [:username, :email])
48
+ if admin? # admins may edit username and email but not password
49
+ @user.assign(params[:user], [:username, :email])
50
+ else # username isn't editable
51
+ @user.assign(params[:user], [:email, :password, :password_confirmation])
52
+ end
57
53
  @user.save!
58
54
  ...
59
55
  end
@@ -64,13 +60,13 @@ If you don't always want to set attribute lists, you may use the mass_assignment
64
60
 
65
61
  <pre><code>
66
62
  class User < ActiveRecord::Base
67
- # The boring usage. You may as well specify attributes at calltime.
63
+ # The boring usage. You're better off passing attributes to assign() in the controller.
68
64
  mass_assignment_policy :only => [:email, :username]
69
-
65
+
70
66
  # More interesting. No id fields!
71
67
  mass_assignment_policy :except => /_id$/
72
68
  end
73
-
69
+
74
70
  # Hardcore. Disables mass assignment globally unless overridden!
75
71
  ActiveRecord::Base.mass_assignment_policy :except => :all
76
72
  </code></pre>
@@ -85,7 +81,7 @@ Nested assignment is supported by passing hashes and arrays for the whitelist.
85
81
  class Pirate < ActiveRecord::Base
86
82
  accepts_nested_attributes_for :ships
87
83
  end
88
-
84
+
89
85
  class PiratesController < ApplicationController
90
86
  def update
91
87
  @pirate = Pirate.find(params[:id])
@@ -114,16 +110,3 @@ Sometimes nested assignment isn't completely appropriate but you still need to a
114
110
  </code></pre>
115
111
 
116
112
  The major benefit here is that the block won't yield unless the params exist, so you don't need to check 'if params[:ship] && params[:ship][:pirate]'.
117
-
118
- h3. Feedback
119
-
120
- I can think of a couple alternate implementations for this API. Consider:
121
-
122
- @user.assign(params[:user], [:username, :email])
123
-
124
- vs
125
-
126
- @user.assign(params[:user], :only => [:username, :email])
127
- @user.assign(params[:user], :except => [:admin])
128
-
129
- I personally prefer the former because I think that blacklists are inherently less safe than whitelists, with no compensating advantage. But I'd love to hear some other use cases and get feedback on this! Fork this repo and send pull requests or just contact me (github.com/cainlevy). Let's talk.
@@ -1,6 +1,4 @@
1
1
  module MassAssignment
2
- VERSION = '1.0.0'
3
-
4
2
  def self.included(base)
5
3
  base.class_eval do extend ClassMethods end
6
4
  end
@@ -89,3 +87,5 @@ module MassAssignment
89
87
  end
90
88
  end
91
89
  end
90
+
91
+ ActiveRecord::Base.class_eval do include MassAssignment end
data/test/test_helper.rb CHANGED
@@ -1,12 +1,8 @@
1
1
  require 'rubygems'
2
2
  require 'test/unit'
3
- gem 'rails', '3.0.6'
3
+ gem 'rails', '3.0.7'
4
4
  require 'active_support'
5
5
  require 'active_support/test_case'
6
6
  require 'active_record'
7
-
8
- PLUGIN_ROOT = File.dirname(__FILE__) + '/../'
9
- ActiveSupport::Dependencies.autoload_paths << File.join(PLUGIN_ROOT, 'lib')
10
- require 'rails/init'
11
-
7
+ require 'mass_assignment'
12
8
  require 'mocha'
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mass_assignment
3
3
  version: !ruby/object:Gem::Version
4
- hash: 23
4
+ hash: 21
5
5
  prerelease: false
6
6
  segments:
7
7
  - 1
8
8
  - 0
9
- - 0
10
- version: 1.0.0
9
+ - 1
10
+ version: 1.0.1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Lance Ivy
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-04-13 00:00:00 -07:00
18
+ date: 2011-08-16 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -45,7 +45,6 @@ files:
45
45
  - LICENSE
46
46
  - README.textile
47
47
  - Rakefile
48
- - rails/init.rb
49
48
  - test/test_helper.rb
50
49
  - test/mass_assignment_test.rb
51
50
  has_rdoc: true
data/rails/init.rb DELETED
@@ -1 +0,0 @@
1
- ActiveRecord::Base.class_eval do include MassAssignment end