cancan_strong_parameters 0.2.1 → 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -16,4 +16,5 @@ test/tmp
16
16
  test/version_tmp
17
17
  tmp
18
18
  .DS_Store
19
- log/
19
+ log/
20
+ test/log/
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 1.9.2
5
+ - 1.8.7
data/README.md CHANGED
@@ -1,14 +1,12 @@
1
1
  # CancanStrongParameters
2
2
 
3
- CanCan and [strong_parameters](https://github.com/rails/strong_parameters) are friends now!
3
+ [CanCan](ryanb/cancan) and [strong_parameters](rails/strong_parameters) are friends now!
4
4
 
5
5
  [![Build Status](https://secure.travis-ci.org/colinyoung/cancan_strong_parameters.png)](http://travis-ci.org/colinyoung/cancan_strong_parameters)
6
6
 
7
7
  ## Authors
8
8
 
9
- The majority of this gem is credited to @mckeed, who posted this gist: https://gist.github.com/2878508
10
- I (@colinyoung) helped put some of it together.
11
-
9
+ The majority of this gem is credited to @mckeed, who posted this gist: https://gist.github.com/2878508. I (@colinyoung) helped put some of it together.
12
10
 
13
11
  ## Installation
14
12
 
@@ -26,14 +24,40 @@ Or install it yourself as:
26
24
 
27
25
  ## Usage
28
26
 
29
- 1. Add it to your Gemfile
30
- 2. Wherever you use `load_and_authorize_resource`, also add:
31
-
32
- class PostsController < ApplicationController
33
- ...
34
- load_and_authorize_resource
35
- permit_params post: [:name, :title, author: {:name}]
36
- end
27
+ 1. Add `gem "cancan_strong_parameters"` to your Gemfile
28
+ 2. Wherever you use `load_and_authorize_resource`, also permit your parameters:
29
+
30
+ ```ruby
31
+ class PostsController < ApplicationController
32
+ ...
33
+ load_and_authorize_resource
34
+
35
+ permit_params :body, tags: [:name]
36
+ # --> permit_params allows parameters but doesn't require them.
37
+ # In the preceding, :tags are a nested resource of post, while
38
+ # :body is an attribute of a Post.
39
+ #
40
+ # :tags is plural here because it's a has_many association, but
41
+ # you should use a singular key for a has_one.
42
+
43
+ require_params :title
44
+ # --> require_params works exactly the same, but throws an error
45
+ # if the parameter isn't provided.
46
+
47
+ # You can also require/permit params on create or update only:
48
+ permit_params_on_create ...
49
+ permit_params_on_update ...
50
+ require_params_on_create ...
51
+ end
52
+ ```
53
+ 3. Finally, don't forget to make the vars you use in your controllers
54
+ accessible in your models:
55
+
56
+ ```ruby
57
+ class Post < ActiveRecord::Base
58
+ attr_accessible :title, :body, :tags_attributes
59
+ end
60
+ ```
37
61
 
38
62
  ## Testing
39
63
 
@@ -49,6 +73,7 @@ Run with `bundle exec rake test`.
49
73
 
50
74
  ## Changelog
51
75
 
76
+ * Fixed docs to be compatible with 0.1.5.
52
77
  * Fixed some issues with nested form subfields in `permit_params`
53
78
  * Made compatible for nested forms
54
79
  * Added default allows for _destroy.
@@ -14,8 +14,8 @@ Gem::Specification.new do |gem|
14
14
 
15
15
  gem.add_development_dependency "require_all"
16
16
  gem.add_development_dependency "minitest", "~> 3.0"
17
+ gem.add_development_dependency "minitest_tu_shim"
17
18
  gem.add_development_dependency "rails"
18
- gem.add_development_dependency "debugger"
19
19
 
20
20
  gem.files = `git ls-files`.split($\)
21
21
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
@@ -1,4 +1,4 @@
1
- require "active_support/hash_with_indifferent_access"
1
+ require "cancan_strong_parameters/ruby/hash"
2
2
  require "cancan_strong_parameters/version"
3
3
  require "cancan_strong_parameters/controller"
4
4
  require "cancan_strong_parameters/deep_permit"
@@ -1,7 +1,7 @@
1
1
  module CancanStrongParameters
2
2
  module Controller
3
3
 
4
- HASH_DEFAULTS = [:id, :_destroy, :_delete]
4
+ HASH_DEFAULTS = ['id', '_destroy', '_delete']
5
5
 
6
6
  module ClassMethods
7
7
  # Use this with CanCan's load_resource to permit a set of params before
@@ -72,11 +72,24 @@ module CancanStrongParameters
72
72
  if (hash.present? && keys.present?) || (hash.select{|k,v| v.is_a?(Array)} == hash)
73
73
 
74
74
  defaults = CancanStrongParameters::Controller::HASH_DEFAULTS
75
- hash = hash.attributized
75
+
76
+ # @todo We have to stringify everything for 1.8.7 due to a bug in `strong_parameters`.
77
+ # More at https://github.com/rails/strong_parameters/pull/51
78
+ hash = hash.attributized.stringified
76
79
 
77
80
  prepend_before_filter :only => actions do
78
81
  resource_name = self.class.resource_name
79
- self.params[resource_name] = params[resource_name].standardized.send method, *[*keys.flatten + defaults, hash]
82
+
83
+ # @todo We have to stringify everything for 1.8.7 due to a bug in `strong_parameters`.
84
+ # More at https://github.com/rails/strong_parameters/pull/51
85
+ parameters = keys.flatten.map! {|k| k.to_s } + defaults
86
+ parameters << ActionController::Parameters.new(hash)
87
+
88
+ # original: parameters = keys.flatten + defaults
89
+ # parameters << hash
90
+ return warn("Not updating - no parameters key present for #{resource_name}") unless params[resource_name]
91
+
92
+ self.params[resource_name] = params[resource_name].standardized.send method, *parameters
80
93
  end
81
94
  elsif hash.present?
82
95
  prepend_before_filter :only => actions do
@@ -86,9 +99,9 @@ module CancanStrongParameters
86
99
  prepend_before_filter :only => actions do
87
100
  resource_name = self.class.resource_name
88
101
  if params.has_key?(resource_name)
89
- self.params[resource_name] = params[resource_name].send method, *keys
102
+ self.params[resource_name] = params[resource_name].send method, *keys.stringified
90
103
  else
91
- self.params = params.send method, *keys
104
+ self.params = params.send method, *keys.stringified
92
105
  end
93
106
  end
94
107
  end
@@ -106,6 +119,12 @@ module CancanStrongParameters
106
119
  def self.included(base)
107
120
  base.extend(ClassMethods)
108
121
  end
122
+
123
+ # Errors
124
+ def warn msg
125
+ return unless Rails and Rails.logger
126
+ Rails.logger.warn(msg)
127
+ end
109
128
 
110
129
  end
111
130
  end
@@ -184,4 +203,39 @@ class String
184
203
  def is_hex?
185
204
  !!(self =~ /^[0-9a-f]+$/)
186
205
  end
206
+ end
207
+
208
+ # @todo Can be remove when new version of `strong_parameters` (>=0.1.5) is released.
209
+ class Hash
210
+ def stringified
211
+ Hash.new.tap do |h|
212
+ each do |key, value|
213
+ value = case value
214
+ when Symbol
215
+ value.to_s
216
+ when Hash
217
+ value.indifferent
218
+ when Array
219
+ value.stringified
220
+ end
221
+ h[key.to_s] = value
222
+ end
223
+ end
224
+ end
225
+ end
226
+
227
+ class Array
228
+ def stringified
229
+ Array.new.tap do |a|
230
+ each do |value|
231
+ value = if value.is_a? Hash
232
+ value.stringified.indifferent
233
+ else
234
+ value.to_s
235
+ end
236
+
237
+ a << value
238
+ end
239
+ end
240
+ end
187
241
  end
@@ -0,0 +1,8 @@
1
+ require "active_support/hash_with_indifferent_access"
2
+
3
+ class Hash
4
+ def indifferent
5
+ ActiveSupport::HashWithIndifferentAccess.new(self)
6
+ end
7
+ alias :indifferent_access :indifferent
8
+ end
@@ -1,3 +1,3 @@
1
1
  module CancanStrongParameters
2
- VERSION = "0.2.1"
2
+ VERSION = "0.2.2"
3
3
  end
@@ -2,22 +2,23 @@ class PostsController < ActionController::Base
2
2
  include CancanStrongParameters::Controller
3
3
 
4
4
  permit_params :title, :content,
5
- comments: [
6
- :body, tags: [:name]
5
+ :comments => [
6
+ :body,
7
+ { :tags => [ :name ] } # This is fugly, use 1.9!
7
8
  ]
8
9
 
9
10
  def create
10
11
  @post = Post.new(params[:post])
11
12
  @post_attributes = params[:post]
12
- render json: @post
13
+ render :json => @post
13
14
  end
14
15
 
15
16
  def update
16
17
  @post = Post.find(params[:id])
17
18
  if @post.update_attributes(params[:post])
18
- render json: @post
19
+ render :json => @post
19
20
  else
20
- render json: { errors: @post.errors.full_messages }, status: :unprocessable_entity
21
+ render :json => { :errors => post.errors.full_messages }, :status => :unprocessable_entity
21
22
  end
22
23
  end
23
24
 
@@ -12,7 +12,7 @@ class Post
12
12
 
13
13
  # Fake persistence
14
14
  def self.sample_post
15
- new(title: "Sample post", body: "Sample body")
15
+ new(:title => "Sample post", :body => "Sample body")
16
16
  end
17
17
 
18
18
  def self.find(*args)
@@ -0,0 +1,60 @@
1
+ module MiniTest::Expectations
2
+ def assert_same_content(item, other_item, verb=:assert)
3
+ item.each do |attrs|
4
+ value = attrs.last
5
+ key = attrs.first if attrs.length > 1
6
+
7
+
8
+ other_value = other_item[key] if self.is_a?(Hash)
9
+
10
+ if other_value.present?
11
+ if value.respond_to? :same_as?
12
+ send verb, value.same_as?(other_value), "#{value} was not same as #{other_value}."
13
+ else
14
+ send "#{verb}_equal", value, other_value
15
+ end
16
+ else
17
+ send verb, item.same_as?(other_item), "#{item} was not the same as #{other_item}."
18
+ end
19
+ end
20
+ end
21
+
22
+ def refute_same_content(item, other_item)
23
+ assert_same_content(item, other_item, :refute)
24
+ end
25
+ end
26
+
27
+ class Array
28
+ def same_as?(other_ary)
29
+ cpy = dup
30
+ other_cpy = other_ary.dup
31
+ each do |item|
32
+ case item
33
+ when Array, Hash
34
+ cpy.delete(item) if other_ary.any? { |other_item| other_item.same_as?(item) && other_cpy.delete(other_item) }
35
+ else
36
+ cpy.delete(item) if other_ary.include?(item) && other_cpy.delete(item)
37
+ end
38
+ end
39
+
40
+ cpy.empty? and other_cpy.empty?
41
+ end
42
+ end
43
+
44
+ class Hash
45
+ def same_as?(other_hsh)
46
+ return false unless self.keys.count == other_hsh.keys.count
47
+ each do |key, value|
48
+ return false unless other_hsh.has_key? key
49
+
50
+ other_value = other_hsh[key]
51
+ if value.respond_to? :same_as?
52
+ return false unless value.same_as? other_value
53
+ else
54
+ return false unless value == other_value
55
+ end
56
+ end
57
+
58
+ true
59
+ end
60
+ end
data/test/config.ru CHANGED
@@ -1 +1 @@
1
- # Empty to make tests work
1
+ # Empty to make tests work
@@ -1,101 +1,97 @@
1
1
  require 'test_helper'
2
2
 
3
3
  class PostsControllerTest < ActionController::TestCase
4
+
4
5
  test "should not clip off deep params" do
5
6
  params = {
6
- post: {
7
- title: "Title of post",
8
- content: "Post main content.",
9
- comments_attributes: [{
10
- body: "My comment.",
11
- tags_attributes: [{
12
- name: "article"
7
+ :post => {
8
+ :title => "Title of post",
9
+ :content => "Post main content.",
10
+ :comments_attributes => [{
11
+ :body => "My comment.",
12
+ :tags_attributes => [{
13
+ :name => "article"
13
14
  }]
14
15
  }]
15
16
  }
16
17
  }
17
18
 
18
19
  post :create, params
19
- assert_equal \
20
- ActiveSupport::HashWithIndifferentAccess.new(assigns(:post_attributes)),
21
- ActiveSupport::HashWithIndifferentAccess.new(params[:post])
20
+ assigns(:post_attributes).indifferent.must_have_same_content_as params[:post].indifferent
22
21
  end
23
22
 
24
23
  test "keeps _destroy keys" do
25
24
  params = {
26
- post: {
27
- _destroy: true
25
+ :post => {
26
+ :_destroy => true
28
27
  }
29
28
  }
30
29
 
31
30
  post :create, params
32
- assert_equal \
33
- ActiveSupport::HashWithIndifferentAccess.new(assigns(:post_attributes)),
34
- ActiveSupport::HashWithIndifferentAccess.new(params[:post])
31
+ assigns(:post_attributes).indifferent.must_have_same_content_as params[:post].indifferent
35
32
  end
36
33
 
37
34
  test "can handle multiple items" do
38
35
  params = {
39
- post: {
40
- title: "Hello",
41
- comments_attributes: {
36
+ :post => {
37
+ :title => "Hello",
38
+ :comments_attributes => {
42
39
  "0" => {
43
- body: "Comment 1",
44
- tags_attributes: {
40
+ :body => "Comment 1",
41
+ :tags_attributes => {
45
42
  "0" => {
46
- name: "article"
43
+ :name => "article"
47
44
  },
48
45
  "1" => {
49
- name: "post"
46
+ :name => "post"
50
47
  },
51
48
  }
52
49
  },
53
50
  "1" => {
54
- body: "Comment 2"
51
+ :body => "Comment 2"
55
52
  },
56
53
  "new_3904949" => {
57
- body: "Comment 3"
54
+ :body => "Comment 3"
58
55
  }
59
56
  }
60
57
  }
61
58
  }
62
59
 
63
60
  post :create, params
64
- assert_equal \
65
- ActiveSupport::HashWithIndifferentAccess.new(assigns(:post_attributes)),
66
- ActiveSupport::HashWithIndifferentAccess.new({
67
- title: "Hello",
68
- comments_attributes: [
69
- {
70
- body: "Comment 1",
71
- tags_attributes: [{
72
- name: "article"
73
- },
74
- {
75
- name: "post"
76
- }
77
- ]
78
- },
79
- {
80
- body: "Comment 2"
81
- },
82
- {
83
- body: "Comment 3"
84
- }
85
- ]
86
- })
61
+ expected = {
62
+ :title => "Hello",
63
+ :comments_attributes => [
64
+ {
65
+ :body => "Comment 1",
66
+ :tags_attributes => [{
67
+ :name => "post"
68
+ },
69
+ {
70
+ :name => "article"
71
+ }
72
+ ]
73
+ },
74
+ {
75
+ :body => "Comment 2"
76
+ },
77
+ {
78
+ :body => "Comment 3"
79
+ }
80
+ ]
81
+ }
82
+ assigns(:post_attributes).must_have_same_content_as expected.indifferent
87
83
  end
88
84
 
89
- test "can handle multiple items but with only new itesm" do
85
+ test "can handle multiple items but with only new items" do
90
86
  params = {
91
- post: {
92
- title: "Hello",
93
- comments_attributes: {
87
+ :post => {
88
+ :title => "Hello",
89
+ :comments_attributes => {
94
90
  "new_3904949" => {
95
- body: "Comment 3",
96
- tags_attributes: {
91
+ :body => "Comment 3",
92
+ :tags_attributes => {
97
93
  "new_23040234" => {
98
- name: "article"
94
+ :name => "article"
99
95
  }
100
96
  }
101
97
  }
@@ -104,16 +100,15 @@ class PostsControllerTest < ActionController::TestCase
104
100
  }
105
101
 
106
102
  post :create, params
107
- assert_equal \
108
- ActiveSupport::HashWithIndifferentAccess.new(assigns(:post_attributes)),
109
- ActiveSupport::HashWithIndifferentAccess.new({
110
- title: "Hello",
111
- comments_attributes: [{
112
- body: "Comment 3",
113
- tags_attributes: [{
114
- name: "article"
115
- }]
103
+ expected = {
104
+ :title => "Hello",
105
+ :comments_attributes => [{
106
+ :body => "Comment 3",
107
+ :tags_attributes => [{
108
+ :name => "article"
116
109
  }]
117
- })
110
+ }]
111
+ }
112
+ assigns(:post_attributes).indifferent.must_have_same_content_as expected.indifferent
118
113
  end
119
114
  end
@@ -6,9 +6,9 @@ class TitleControllerTest < ActionController::TestCase
6
6
 
7
7
  new_title = 'Changed title'
8
8
  put :update,
9
- id: 1,
10
- post: {
11
- title: new_title
9
+ :id => 1,
10
+ :post => {
11
+ :title => new_title
12
12
  }
13
13
 
14
14
  assert_equal assigns[:post].title, new_title
data/test/rails_helper.rb CHANGED
@@ -5,8 +5,6 @@ ENV["RAILS_ENV"] ||= 'test'
5
5
 
6
6
  require 'rubygems'
7
7
 
8
- require 'debugger'
9
-
10
8
  gem 'actionpack', '>= 3.0.0'
11
9
  gem 'activesupport', '>= 3.0.0'
12
10
  gem 'activemodel', '>= 3.0.0'
@@ -35,5 +33,5 @@ Config::Application.initialize!
35
33
  Config::Application.routes.draw do
36
34
  resources :posts
37
35
 
38
- match 'title/:id', to: 'title#update', via: :put
36
+ match 'title/:id', :to => 'title#update', :via => :put
39
37
  end
data/test/test_helper.rb CHANGED
@@ -8,3 +8,11 @@ require 'cancan_strong_parameters'
8
8
  ## Boot up an instance of rails
9
9
  require 'rails_helper'
10
10
  require 'rails/test_help'
11
+
12
+ ## Custom matchers
13
+ require 'assertions/assert_same_content'
14
+
15
+ module MiniTest::Expectations
16
+ infect_an_assertion :assert_same_content, :must_have_same_content_as
17
+ infect_an_assertion :refute_same_content, :wont_have_same_content_as
18
+ end
@@ -0,0 +1,34 @@
1
+ require 'test_helper'
2
+
3
+ class SameContentTest < Test::Unit::TestCase
4
+
5
+ def test_same_content_works
6
+ ['a', 'b', 'c'].must_have_same_content_as ['b', 'a', 'c']
7
+ ['a', 'b', 'c'].wont_have_same_content_as ['b', 'a', 'c', 'd']
8
+
9
+ dog1 = {
10
+ :breed => "Husky/Lab Mix",
11
+ :name => "Rue",
12
+ :tricks => {
13
+ :not_jumping_up => false, # :( Workin on it!
14
+ :sitting => true,
15
+ :coming_when_called => true,
16
+ :other => [
17
+ {
18
+ :name => "trick1",
19
+ :value => false
20
+ },
21
+ {
22
+ :name => "trick2",
23
+ :value => true
24
+ }
25
+ ]
26
+ }
27
+ }
28
+
29
+ dog2 = dog1.dup
30
+ dog2[:tricks][:other].reverse!
31
+ dog1.must_have_same_content_as dog2
32
+ end
33
+
34
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cancan_strong_parameters
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-11-24 00:00:00.000000000 Z
12
+ date: 2012-11-29 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: cancan
@@ -92,7 +92,7 @@ dependencies:
92
92
  - !ruby/object:Gem::Version
93
93
  version: '3.0'
94
94
  - !ruby/object:Gem::Dependency
95
- name: rails
95
+ name: minitest_tu_shim
96
96
  requirement: !ruby/object:Gem::Requirement
97
97
  none: false
98
98
  requirements:
@@ -108,7 +108,7 @@ dependencies:
108
108
  - !ruby/object:Gem::Version
109
109
  version: '0'
110
110
  - !ruby/object:Gem::Dependency
111
- name: debugger
111
+ name: rails
112
112
  requirement: !ruby/object:Gem::Requirement
113
113
  none: false
114
114
  requirements:
@@ -131,6 +131,7 @@ extensions: []
131
131
  extra_rdoc_files: []
132
132
  files:
133
133
  - .gitignore
134
+ - .travis.yml
134
135
  - Gemfile
135
136
  - LICENSE
136
137
  - README.md
@@ -140,16 +141,19 @@ files:
140
141
  - lib/cancan_strong_parameters/controller.rb
141
142
  - lib/cancan_strong_parameters/deep_permit.rb
142
143
  - lib/cancan_strong_parameters/rails/controller/base.rb
144
+ - lib/cancan_strong_parameters/ruby/hash.rb
143
145
  - lib/cancan_strong_parameters/version.rb
144
146
  - test/app/controllers/posts_controller.rb
145
147
  - test/app/controllers/title_controller.rb
146
148
  - test/app/models/post.rb
149
+ - test/assertions/assert_same_content.rb
147
150
  - test/config.ru
148
151
  - test/functional/posts_controller_test.rb
149
152
  - test/functional/title_controller_test.rb
150
153
  - test/rails_helper.rb
151
154
  - test/script/rails
152
155
  - test/test_helper.rb
156
+ - test/unit/assert_same_content_test.rb
153
157
  homepage: https://github.com/colinyoung/cancan_strong_parameters
154
158
  licenses: []
155
159
  post_install_message:
@@ -178,9 +182,11 @@ test_files:
178
182
  - test/app/controllers/posts_controller.rb
179
183
  - test/app/controllers/title_controller.rb
180
184
  - test/app/models/post.rb
185
+ - test/assertions/assert_same_content.rb
181
186
  - test/config.ru
182
187
  - test/functional/posts_controller_test.rb
183
188
  - test/functional/title_controller_test.rb
184
189
  - test/rails_helper.rb
185
190
  - test/script/rails
186
191
  - test/test_helper.rb
192
+ - test/unit/assert_same_content_test.rb