alfred 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -1 +1,4 @@
1
- rvm: 1.9.2
1
+ rvm:
2
+ - 1.9.2
3
+ - 1.9.3
4
+ - ruby-head
@@ -0,0 +1,120 @@
1
+ h1. Alfred - the unobtrusive butler who takes care of the uninvited guests "!https://secure.travis-ci.org/parcydo/alfred.png?branch=master!":http://travis-ci.org/parcydo/alfred
2
+
3
+ Travis is an attempt to create an open-source, distributed build system for the Ruby community that:
4
+
5
+ 1. allows open-source projects to register their repository and have their test-suites run on demand
6
+ 2. allows users to contribute build capacities by connecting a VM that runs a build agent somewhere on their underused servers
7
+
8
+ h2. Contact
9
+ * "Github":http://github.com/parcydo
10
+ * "Twitter":http://twitter.com/parcydo
11
+
12
+ h2. Documentation
13
+
14
+ * "Wiki":http://github.com/parcydo/alfred/wiki
15
+ * "YARD":http://rdoc.info/github/parcydo/alfred
16
+
17
+ h2. Preview
18
+
19
+ h3. Without Alfred, and with much mess:
20
+
21
+ <pre>
22
+ # app/models/user.rb
23
+ class User < ActiveRecord::Base
24
+ attr_accessible :email, :password, :password_confirmation
25
+ attr_accessible :email, :password, :password_confirmation, :username, as: :admin
26
+ attr_accessible :email, :password, :password_confirmation, :username, as: :on_create
27
+ end
28
+ </pre>
29
+
30
+ Have to use a special role:
31
+
32
+ <pre>
33
+ # app/controllers/users_controlelr.rb
34
+ class UsersController < ApplicationController
35
+ def create
36
+ @user = User.create(params[:user], as: :on_create)
37
+ end
38
+ end
39
+ </pre>
40
+
41
+ h3. With Alfred and no hassles:
42
+
43
+ <pre>
44
+ # app/models/user.rb
45
+ class User < ActiveRecord::Base
46
+ alfred_accessible :email, :password
47
+ alfred_accessible :username, as: :admin
48
+ alfred_accessible :username, on: :create
49
+ end
50
+ </pre>
51
+
52
+ Nothing special here:
53
+
54
+ <pre>
55
+ # app/controllers/users_controlelr.rb
56
+ class UsersController < ApplicationController
57
+ def create
58
+ @user = User.create(params[:user])
59
+ end
60
+ end
61
+ </pre>
62
+
63
+ h2. Usage
64
+
65
+ alfred_accessible and alfred_protected behaves just like attr_accessible and attr_protected on steroids.
66
+
67
+ h3. accessible and protected
68
+
69
+ <pre>
70
+ class User < ActiveRecord::Base
71
+ alfred_accessible :a, :b
72
+ alfred_protected :c, :d
73
+ end
74
+ </pre>
75
+
76
+ h3. roles
77
+
78
+ Custom inherits from default role:
79
+
80
+ <pre>
81
+ class User < ActiveRecord::Base
82
+ alfred_accessible :a, :b
83
+ alfred_accessible :c, :d, as: :custom
84
+ end
85
+ </pre>
86
+
87
+ h3. custom inheritance
88
+
89
+ <pre>
90
+ class User < ActiveRecord::Base
91
+ alfred_accessible :a, :b
92
+ alfred_accessible :c, :d, as: :custom
93
+ alfred_accessible :e, :f, as: :custom2, inherit: :custom
94
+ end
95
+ </pre>
96
+
97
+ h3. events
98
+
99
+ <pre>
100
+ class User < ActiveRecord::Base
101
+ alfred_accessible :a, :b
102
+ alfred_accessible :c, :d, on: :create
103
+ alfred_accessible :e, :f, on: :update
104
+ end
105
+ </pre>
106
+
107
+ h3. passwords
108
+
109
+ password_confirmation will automatically added by default.
110
+
111
+ <pre>
112
+ class User < ActiveRecord::Base
113
+ alfred_accessible :password
114
+ end
115
+ </pre>
116
+
117
+ h2. Requirements
118
+
119
+ * Ruby 1.9.2 (Ruby 1.9.1 is not supported).
120
+ * Rails 3.1.x (Rails 3.0.x is not supported).
@@ -13,7 +13,8 @@ Gem::Specification.new do |s|
13
13
 
14
14
  s.rubyforge_project = "alfred"
15
15
 
16
- s.add_dependency "rails", "~> 3.1.0.rc"
16
+ s.add_dependency "rails", ">= 3.1.0"
17
+ s.add_development_dependency "activemodel"
17
18
  s.add_development_dependency "activerecord"
18
19
  s.add_development_dependency "rr"
19
20
  s.add_development_dependency "rspec"
@@ -22,4 +23,4 @@ Gem::Specification.new do |s|
22
23
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
24
  s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
25
  s.require_paths = ["lib"]
25
- end
26
+ end
@@ -1,8 +1,6 @@
1
1
  require 'rails'
2
2
 
3
3
  module Alfred
4
- autoload :Models, 'alfred/models'
5
-
6
4
  # Automaticly add password_confirmation if password exists.
7
5
  mattr_accessor :auto_password_confirmation
8
6
  @@auto_password_confirmation = true
@@ -15,4 +13,5 @@ module Alfred
15
13
  end
16
14
 
17
15
  require 'alfred/engine'
16
+ require 'alfred/mass_assignment_security'
18
17
  require 'alfred/orm/active_record' if defined?(ActiveRecord)
@@ -0,0 +1,150 @@
1
+ require 'active_model'
2
+
3
+ module Alfred
4
+ module ActiveModel
5
+ module MassAssignmentSecurity
6
+ module ClassMethods
7
+ # Attributes named in this macro are protected from mass-assignment
8
+ # whenever attributes are sanitized before assignment. A role for the
9
+ # attributes is optional, if no role is provided then :default is used.
10
+ # A role can be defined by using the :as option.
11
+ #
12
+ # Mass-assignment to these attributes will simply be ignored, to assign
13
+ # to them you can use direct writer methods. This is meant to protect
14
+ # sensitive attributes from being overwritten by malicious users
15
+ # tampering with URLs or forms. Example:
16
+ #
17
+ # class Customer
18
+ # include ActiveModel::MassAssignmentSecurity
19
+ # extend Alfred::ActiveModel::MassAssignmentSecurity
20
+ #
21
+ # attr_accessor :name, :credit_rating
22
+ #
23
+ # alfred_protected :credit_rating
24
+ # alfred_protected :last_login, as: :trainee
25
+ #
26
+ # def assign_attributes(values, options = {})
27
+ # sanitize_for_mass_assignment(values, options[:as]).each do |k, v|
28
+ # send("#{k}=", v)
29
+ # end
30
+ # end
31
+ # end
32
+ #
33
+ # When using the :default role :
34
+ #
35
+ # customer = Customer.new
36
+ # customer.assign_attributes({ name: "Daniel", credit_rating: "Excellent", last_login: 1.day.ago }, as: :default)
37
+ # customer.name # => "Daniel"
38
+ # customer.credit_rating # => nil
39
+ # customer.last_login # => nil
40
+ #
41
+ # customer.credit_rating = "Average"
42
+ # customer.credit_rating # => "Average"
43
+ #
44
+ # And using the :admin role :
45
+ #
46
+ # customer = Customer.new
47
+ # customer.assign_attributes({ name: "Daniel", credit_rating: "Excellent", last_login: 1.day.ago }, as: :trainee)
48
+ # customer.name # => "Daniel"
49
+ # customer.credit_rating # => "Excellent"
50
+ # customer.last_login # => nil
51
+ #
52
+ # To start from an all-closed default and enable attributes as needed,
53
+ # have a look at +alfred_accessible+.
54
+ #
55
+ # Note that using <tt>Hash#except</tt> or <tt>Hash#slice</tt> in place of +alfred_protected+
56
+ # to sanitize attributes won't provide sufficient protection.
57
+ def alfred_protected(*args)
58
+ alfred(:protected, *args)
59
+ end
60
+
61
+ # Specifies a white list of model attributes that can be set via
62
+ # mass-assignment.
63
+ #
64
+ # Like +alfred_protected+, a role for the attributes is optional,
65
+ # if no role is provided then :default is used. A role can be defined by
66
+ # using the :as option.
67
+ #
68
+ # This is the opposite of the +alfred_protected+ macro: Mass-assignment
69
+ # will only set attributes in this list, to assign to the rest of
70
+ # attributes you can use direct writer methods. This is meant to protect
71
+ # sensitive attributes from being overwritten by malicious users
72
+ # tampering with URLs or forms. If you'd rather start from an all-open
73
+ # default and restrict attributes as needed, have a look at
74
+ # +alfred_protected+.
75
+ #
76
+ # class Customer
77
+ # include ActiveModel::MassAssignmentSecurity
78
+ # extend Alfred::ActiveModel::MassAssignmentSecurity
79
+ #
80
+ # attr_accessor :name, :credit_rating
81
+ #
82
+ # alfred_accessible :name
83
+ # alfred_accessible :credit_rating, as: :admin
84
+ #
85
+ # def assign_attributes(values, options = {})
86
+ # sanitize_for_mass_assignment(values, options[:as]).each do |k, v|
87
+ # send("#{k}=", v)
88
+ # end
89
+ # end
90
+ # end
91
+ #
92
+ # When using the :default role :
93
+ #
94
+ # customer = Customer.new
95
+ # customer.assign_attributes({ name: "Daniel", credit_rating: "Excellent", last_login: 1.day.ago }, as: :default)
96
+ # customer.name # => "Daniel"
97
+ # customer.credit_rating # => nil
98
+ #
99
+ # customer.credit_rating = "Average"
100
+ # customer.credit_rating # => "Average"
101
+ #
102
+ # And using the :admin role :
103
+ #
104
+ # customer = Customer.new
105
+ # customer.assign_attributes({ name: "Daniel", credit_rating: "Excellent", last_login: 1.day.ago }, as: :admin)
106
+ # customer.name # => "Daniel"
107
+ # customer.credit_rating # => "Excellent"
108
+ #
109
+ # Note that using <tt>Hash#except</tt> or <tt>Hash#slice</tt> in place of +alfred_accessible+
110
+ # to sanitize attributes won't provide sufficient protection.
111
+ def alfred_accessible(*args)
112
+ alfred(:accessible, *args)
113
+ end
114
+
115
+ private
116
+ def alfred(method, *args)
117
+ options = args.extract_options!
118
+
119
+ if args.include?(:password) && Alfred.auto_password_confirmation
120
+ args = args + [:password_confirmation]
121
+ end
122
+
123
+ [nil, :create, :update].each do |action|
124
+ if options[:on]
125
+ next unless options[:on] == action
126
+ end
127
+
128
+ action_args = args.dup
129
+
130
+ role = (options[:as] || :default).to_s
131
+ role << "_#{action}" if action
132
+ role = role.to_sym
133
+
134
+ action_args = action_args + [{ as: role }]
135
+
136
+ action_args = action_args + send("#{method}_attributes", role).to_a.compact.reject { |s| s.blank? }
137
+
138
+ send("attr_#{method}", *action_args)
139
+ end
140
+ end
141
+ end
142
+
143
+ include ClassMethods
144
+ end
145
+ end
146
+ end
147
+
148
+ module ActiveModel::MassAssignmentSecurity::ClassMethods
149
+ include Alfred::ActiveModel::MassAssignmentSecurity
150
+ end
@@ -1,3 +1,32 @@
1
1
  require 'active_record'
2
2
 
3
- ActiveRecord::Base.extend Alfred::Models
3
+ module Alfred
4
+ module ActiveRecord
5
+ module Base
6
+ def assign_attributes(new_attributes, options = {})
7
+ role = (options[:as] || :default).to_s
8
+ role << "_#{options[:action]}" if options[:action]
9
+
10
+ options[:as] = role.to_sym
11
+
12
+ super
13
+ end
14
+
15
+ def initialize(attributes = nil, options = {})
16
+ options[:action] = :create
17
+
18
+ super
19
+ end
20
+
21
+ def update_attributes(attributes, options = {})
22
+ options[:action] = :update
23
+
24
+ super
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ class ActiveRecord::Base
31
+ include Alfred::ActiveRecord::Base
32
+ end
@@ -1,3 +1,3 @@
1
1
  module Alfred
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: alfred
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,22 +9,43 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2011-08-11 00:00:00.000000000Z
12
+ date: 2012-04-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
16
- requirement: &70320733483060 !ruby/object:Gem::Requirement
16
+ requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 3.1.0.rc
21
+ version: 3.1.0
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70320733483060
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 3.1.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: activemodel
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
25
46
  - !ruby/object:Gem::Dependency
26
47
  name: activerecord
27
- requirement: &70320733482640 !ruby/object:Gem::Requirement
48
+ requirement: !ruby/object:Gem::Requirement
28
49
  none: false
29
50
  requirements:
30
51
  - - ! '>='
@@ -32,10 +53,15 @@ dependencies:
32
53
  version: '0'
33
54
  type: :development
34
55
  prerelease: false
35
- version_requirements: *70320733482640
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
36
62
  - !ruby/object:Gem::Dependency
37
63
  name: rr
38
- requirement: &70320733482180 !ruby/object:Gem::Requirement
64
+ requirement: !ruby/object:Gem::Requirement
39
65
  none: false
40
66
  requirements:
41
67
  - - ! '>='
@@ -43,10 +69,15 @@ dependencies:
43
69
  version: '0'
44
70
  type: :development
45
71
  prerelease: false
46
- version_requirements: *70320733482180
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
47
78
  - !ruby/object:Gem::Dependency
48
79
  name: rspec
49
- requirement: &70320733481760 !ruby/object:Gem::Requirement
80
+ requirement: !ruby/object:Gem::Requirement
50
81
  none: false
51
82
  requirements:
52
83
  - - ! '>='
@@ -54,7 +85,12 @@ dependencies:
54
85
  version: '0'
55
86
  type: :development
56
87
  prerelease: false
57
- version_requirements: *70320733481760
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
58
94
  description: Alfred provides better attr_accessor handling on your application.
59
95
  email:
60
96
  - daniel.spangenberg@parcydo.com
@@ -64,16 +100,16 @@ extra_rdoc_files: []
64
100
  files:
65
101
  - .gitignore
66
102
  - .rspec
67
- - .rvmrc
68
103
  - .travis.yml
69
104
  - Gemfile
105
+ - README.textile
70
106
  - Rakefile
71
107
  - alfred.gemspec
72
108
  - lib/alfred.rb
73
109
  - lib/alfred/engine.rb
74
110
  - lib/alfred/generators/alfred/install_generator.rb
75
111
  - lib/alfred/generators/templates/alfred.rb
76
- - lib/alfred/models.rb
112
+ - lib/alfred/mass_assignment_security.rb
77
113
  - lib/alfred/orm/active_record.rb
78
114
  - lib/alfred/version.rb
79
115
  - spec/models_spec.rb
@@ -98,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
98
134
  version: '0'
99
135
  requirements: []
100
136
  rubyforge_project: alfred
101
- rubygems_version: 1.8.8
137
+ rubygems_version: 1.8.21
102
138
  signing_key:
103
139
  specification_version: 3
104
140
  summary: Alfred is the unobtrusive butler who takes care of the uninvited guests.
data/.rvmrc DELETED
@@ -1 +0,0 @@
1
- rvm 1.9.2@alfred --create
@@ -1,53 +0,0 @@
1
- module Alfred
2
- module Models
3
- def alfred_accessible(*args)
4
- alfred(:accessible, *args)
5
- end
6
-
7
- def alfred_protected(*args)
8
- alfred(:protected, *args)
9
- end
10
-
11
- private
12
-
13
- def alfred(method, *args)
14
- options = args.extract_options!
15
-
16
- if options[:as]
17
- if method == :accessible
18
- args = args + accessible_attributes(options[:inherit] || :default).to_a
19
- else
20
- args = args + protected_attributes(options[:inherit] || :default).to_a
21
- end
22
- args = args + [{ as: options[:as] }]
23
- end
24
-
25
- if args.include?(:password) && Alfred.auto_password_confirmation
26
- args = args + [:password_confirmation]
27
- end
28
-
29
- if options[:on] && [:create, :update].include?(options[:on])
30
- if options[:on] == :create
31
- before = :before_create
32
- else
33
- before = :before_update
34
- end
35
- if method == :accessible
36
- self.class.send(:define_method, before) do
37
- attr_accessible(*args)
38
- end
39
- else
40
- self.class.send(:define_method, before) do
41
- attr_protected(*args)
42
- end
43
- end
44
- else
45
- if method == :accessible
46
- attr_accessible(*args)
47
- else
48
- attr_protected(*args)
49
- end
50
- end
51
- end
52
- end
53
- end