specstar-remarkable 0.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/CHANGELOG +147 -0
- data/LICENSE +20 -0
- data/README +103 -0
- data/lib/remarkable/active_record.rb +14 -0
- data/lib/remarkable/active_record/base.rb +6 -0
- data/lib/remarkable/active_record/matchers/accept_nested_attributes_for_matcher.rb +138 -0
- data/lib/remarkable/active_record/matchers/allow_mass_assignment_of_matcher.rb +74 -0
- data/lib/remarkable/active_record/matchers/association_matcher.rb +284 -0
- data/lib/remarkable/active_record/matchers/have_column_matcher.rb +68 -0
- data/lib/remarkable/active_record/matchers/have_default_scope_matcher.rb +68 -0
- data/lib/remarkable/active_record/matchers/have_index_matcher.rb +73 -0
- data/lib/remarkable/active_record/matchers/have_readonly_attributes_matcher.rb +30 -0
- data/lib/remarkable/active_record/matchers/have_scope_matcher.rb +101 -0
- data/lib/remarkable/active_record/matchers/validate_associated_matcher.rb +100 -0
- data/lib/remarkable/active_record/matchers/validate_uniqueness_of_matcher.rb +233 -0
- data/locale/en.yml +264 -0
- metadata +113 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 4d716a190c66558bee739a9a0a68ff8a93829b8d
|
4
|
+
data.tar.gz: 63c5942765d25ca67c72e18a4c90d64fb3aba79c
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c448f82b4c5404739ac5acd9ff763575a4ccae4652121e94c03567457acfaa897f41f9a67e1e427ef3d9e8f0c78dec2ab8a6ccf65e52cb3320a11d75207bdddf
|
7
|
+
data.tar.gz: 4891bb7c7f963b8462505ee4eeb4cf5a008cc6b6803feea4e7d76af13d677b192ba95b27a6f71410c1a34c38e65e05b6bf95bf17c11e6198a48edb638181362e
|
data/CHANGELOG
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
* allow_values_for checks for any message unless otherwise given [#90]
|
2
|
+
|
3
|
+
* Allow booleans to be given to validate_inclusion_of [#89]
|
4
|
+
|
5
|
+
* Allow allow_values_for and allow_mass_assignment_of matchers to be executed in
|
6
|
+
the negative form by including Remarkable::Negative module [#85]
|
7
|
+
|
8
|
+
* Ensure quick subject bypass protected attributes [#87]
|
9
|
+
|
10
|
+
* Added :token and :separator to deal with :tokenizer in validates_length_of [#77]
|
11
|
+
|
12
|
+
* Deprecated validate_format_of. It does not have the same API as the respective
|
13
|
+
ActiveRecord macro, raising questions frequentely about its usage [#76]
|
14
|
+
|
15
|
+
* allow_mass_assignment_of when called without arguments checks if any mass
|
16
|
+
assignment is possible [#80]
|
17
|
+
|
18
|
+
* Add :table_name option to have_index (thanks to Lawrence Pit) [#79]
|
19
|
+
|
20
|
+
* Allow default subject attributes to be given [#74]
|
21
|
+
You can even mix with a fixture replacement tool and still use quick subjects:
|
22
|
+
|
23
|
+
describe Post
|
24
|
+
# Fixjour example
|
25
|
+
subject_attributes { valid_post_attributes }
|
26
|
+
|
27
|
+
describe :published => true do
|
28
|
+
should_validate_presence_of :published_at
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
* Bug fix when a symbol is given has join table to habtm association [#75]
|
33
|
+
|
34
|
+
* Association matchers now searches in the right database for tables [#73]
|
35
|
+
|
36
|
+
* validate_length_of accepts :with_kind_of to enable it to work with associations [#69]
|
37
|
+
In your Post specs now you can write:
|
38
|
+
|
39
|
+
should_validate_length_of :comments, :maximum => 10, :with_kind_of => Comment
|
40
|
+
|
41
|
+
# v3.1
|
42
|
+
|
43
|
+
* Allow validate_presence_of to work with associations [#63]
|
44
|
+
|
45
|
+
* Allow validate_uniqueness_of to work when scopes are not stringfiable values.
|
46
|
+
You can now give timestamps, datetime, date and boolean as scopes [#60]
|
47
|
+
|
48
|
+
* Allow subjects to be overwriten quickly (quick subjects):
|
49
|
+
|
50
|
+
describe Post
|
51
|
+
should_validate_presente_of :title
|
52
|
+
|
53
|
+
describe :published => true do
|
54
|
+
should_validate_presence_of :published_at
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
Is the same as:
|
59
|
+
|
60
|
+
describe Post
|
61
|
+
should_validate_presente_of :title
|
62
|
+
|
63
|
+
describe "when published is true" do
|
64
|
+
subject { Post.new(:published => true) }
|
65
|
+
should_validate_presence_of :published_at
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
And the string can be also localized using I18n [#57]
|
70
|
+
|
71
|
+
[COMPATIBILITY] validate_associated no longer accepts a block to confgure the
|
72
|
+
builder:
|
73
|
+
|
74
|
+
should_validate_associated(:tasks){ |p| p.tasks.build(:captcha => 'i_am_a_robot') }
|
75
|
+
|
76
|
+
The right way to do this is by giving an option called builder and a proc:
|
77
|
+
|
78
|
+
should_validate_associated :tasks, :builder => proc{ |p| p.tasks.build(:captcha => 'i_am_a_robot') }
|
79
|
+
|
80
|
+
* validate_uniqueness_of and accept_nested_attributes_for now use the new
|
81
|
+
interpolation option {{sentence}} [#58]
|
82
|
+
|
83
|
+
* Added accept_nested_attributes_for matcher [#39]
|
84
|
+
|
85
|
+
* Added have_default_scope matcher [#38]
|
86
|
+
|
87
|
+
* Allow :conditions, :include, :joins, :limit, :offset, :order, :select, :readonly,
|
88
|
+
:group, :having, :from, :lock as quick accessors to have_scope matcher
|
89
|
+
|
90
|
+
* Allow all kind of objects to be sent to have_scope (including datetimes, arrays,
|
91
|
+
booleans and nil) (thanks to Szymon Nowak and Nolan Eakins) [#53]
|
92
|
+
|
93
|
+
* Added support to sql options in association_matcher: select, conditions, include,
|
94
|
+
group, having, order, limit and offset, plus finder_sql and counter_sql. [#48]
|
95
|
+
|
96
|
+
* :source and :source_type are now supported by association matcher [#47]
|
97
|
+
|
98
|
+
* validate_inclusion_of became smarter since it now tests invalid values too [#36]
|
99
|
+
|
100
|
+
* Fixed three bugs in validate_uniqueness_of matcher [#42] [#40] [#37]
|
101
|
+
|
102
|
+
# v3.0
|
103
|
+
|
104
|
+
* Added more options to associations matcher. Previously it was handling just
|
105
|
+
:dependent and :through options. Now it deals with:
|
106
|
+
|
107
|
+
:through, :class_name, :foreign_key, :dependent, :join_table, :uniq,
|
108
|
+
:readonly, :validate, :autosave, :counter_cache, :polymorphic
|
109
|
+
|
110
|
+
And they are much smarter! In :join_table and :through cases, they also test if
|
111
|
+
the table exists or not. :counter_cache and :foreign_key also checks if the
|
112
|
+
column exists or not.
|
113
|
+
|
114
|
+
[COMPATIBILITY] Removed callback, have_instance_method and have_class_method
|
115
|
+
matchers. They don't lead to a good TDD since you should test they behavior
|
116
|
+
and not wether they exist or not.
|
117
|
+
|
118
|
+
[COMPATIBILITY] ActiveRecord matches does not pick the instance variable from
|
119
|
+
the spec environment. So we should target only rspec versions that supports
|
120
|
+
subjects (>= 1.1.12).
|
121
|
+
|
122
|
+
Previously, when we are doing this:
|
123
|
+
|
124
|
+
describe Product
|
125
|
+
before(:each){ @product = Product.new(:tangible => true) }
|
126
|
+
should_validate_presence_of :size
|
127
|
+
end
|
128
|
+
|
129
|
+
It was validating the @product instance variable. However this might be not
|
130
|
+
clear. The right way to do that (with subjects) is:
|
131
|
+
|
132
|
+
describe Product
|
133
|
+
subject{ Product.new(:tangible => true) }
|
134
|
+
should_validate_presence_of :size
|
135
|
+
end
|
136
|
+
|
137
|
+
Is also valid to remember that previous versions of Remarkable were overriding
|
138
|
+
subject definitions on rspec. This was also fixed.
|
139
|
+
|
140
|
+
# v2.x
|
141
|
+
|
142
|
+
* Added associations, allow_mass_assignment, allow_values_for, have_column,
|
143
|
+
have_index, have_scope, have_readonly_attributes, validate_acceptance_of,
|
144
|
+
validate_associated, validate_confirmation_of, validate_exclusion_of,
|
145
|
+
validate_inclusion_of, validate_length_of, validate_numericality_of,
|
146
|
+
validate_presence_of and validate_uniqueness_of matchers.
|
147
|
+
|
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Carlos Brando
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
= Remarkable ActiveRecord
|
2
|
+
|
3
|
+
Remarkable ActiveRecord is a collection of matchers to ActiveRecord. Why use
|
4
|
+
Remarkable?
|
5
|
+
|
6
|
+
* Matchers for all ActiveRecord validations, with support to all options. The only
|
7
|
+
exceptions are validate_format_of (which should be invoked as allow_values_for)
|
8
|
+
and the :on option;
|
9
|
+
|
10
|
+
* Matchers for all ActiveRecord associations. The only one which supports all
|
11
|
+
these options:
|
12
|
+
|
13
|
+
:through, :source, :source_type, :class_name, :foreign_key, :dependent,
|
14
|
+
:join_table, :uniq, :readonly, :validate, :autosave, :counter_cache, :polymorphic
|
15
|
+
|
16
|
+
Plus Arel scopes:
|
17
|
+
|
18
|
+
:select, :where, :include, :group, :having, :order, :limit, :offset
|
19
|
+
|
20
|
+
Besides in Remarkable 3.0 matchers became much smarter. Whenever :join_table
|
21
|
+
or :through is given as option, it checks if the given table exists. Whenever
|
22
|
+
:foreign_key or :counter_cache is given, it checks if the given column exists;
|
23
|
+
|
24
|
+
* Tests and more tests. We have a huge tests suite ready to run and tested in
|
25
|
+
ActiveRecord 2.1.2, 2.2.2 and 2.3.2;
|
26
|
+
|
27
|
+
* Great documentation;
|
28
|
+
|
29
|
+
* I18n.
|
30
|
+
|
31
|
+
== Installation
|
32
|
+
|
33
|
+
sudo gem install remarkable_activerecord --pre
|
34
|
+
|
35
|
+
Add this to your Gemfile:
|
36
|
+
|
37
|
+
group :test do
|
38
|
+
gem 'remarkable_activerecord', '>=4.0.0.alpha2'
|
39
|
+
end
|
40
|
+
|
41
|
+
Drop this into your spec/spec_helper.rb or spec/support/remarkable.rb file:
|
42
|
+
|
43
|
+
require 'remarkable/active_record'
|
44
|
+
|
45
|
+
This will also automatically load remarkable/active_model and add those matchers as well.
|
46
|
+
|
47
|
+
== Examples
|
48
|
+
|
49
|
+
All Remarkable macros can be accessed in two different ways. For those who prefer the Shoulda style, let’s look at some model tests:
|
50
|
+
|
51
|
+
describe Post do
|
52
|
+
should_belong_to :user
|
53
|
+
should_have_many :comments
|
54
|
+
should_have_and_belong_to_many :tags
|
55
|
+
|
56
|
+
should_validate_presence_of :body
|
57
|
+
should_validate_presence_of :title
|
58
|
+
should_validate_uniqueness_of :title, :allow_blank => true
|
59
|
+
end
|
60
|
+
|
61
|
+
For those who likes more the RSpec way can simply do:
|
62
|
+
|
63
|
+
describe Post do
|
64
|
+
it { should belong_to(:user) }
|
65
|
+
it { should have_many(:comments) }
|
66
|
+
it { should have_and_belong_to_many(:tags) }
|
67
|
+
|
68
|
+
it { should validate_presence_of(:body) }
|
69
|
+
it { should validate_presence_of(:title) }
|
70
|
+
it { should validate_uniqueness_of(:title, :allow_blank => true) }
|
71
|
+
end
|
72
|
+
|
73
|
+
== I18n
|
74
|
+
|
75
|
+
All matchers come with I18n support. If you want to translate your matchers,
|
76
|
+
grab make a copy of locale/en.yml and start to translate it.
|
77
|
+
|
78
|
+
Then add your new locale file to Remarkable in spec/support/remarkable.rb:
|
79
|
+
|
80
|
+
Remarkable.add_locale 'path/to/my_locale.yml'
|
81
|
+
|
82
|
+
And then:
|
83
|
+
|
84
|
+
Remarkable.locale = :my_locale
|
85
|
+
|
86
|
+
== Using it outside Rails
|
87
|
+
|
88
|
+
If you want to use Remarkable ActiveRecord outside Rails, you have to remember
|
89
|
+
a few things:
|
90
|
+
|
91
|
+
1. Internationalization is powered by the I18n gem. If you are using it with Rails,
|
92
|
+
it will use the built in gem, otherwise you will have to install the gem by hand:
|
93
|
+
|
94
|
+
gem sources -a http://gems.github.com
|
95
|
+
sudo gem install svenfuchs-i18n
|
96
|
+
|
97
|
+
2. Include the matchers. Remarkable Rails gem is the responsable to add
|
98
|
+
ActiveRecord matchers to rspec. If you are not using it, you have to do:
|
99
|
+
|
100
|
+
Remarkable.include_matchers!(Remarkable::ActiveRecord, RSpec::Core::ExampleGroup)
|
101
|
+
|
102
|
+
This will make ActiveRecord matchers available in all rspec example groups.
|
103
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# Load Remarkable
|
2
|
+
require 'remarkable/active_model'
|
3
|
+
require 'remarkable/active_record/base'
|
4
|
+
|
5
|
+
# Add default locale
|
6
|
+
dir = File.dirname(__FILE__)
|
7
|
+
Dir["#{dir}/../../locale/*yml"].each {|f| Remarkable.add_locale(f) }
|
8
|
+
|
9
|
+
# Add matchers
|
10
|
+
Dir[File.join(dir, 'active_record', 'matchers', '*.rb')].each do |file|
|
11
|
+
require file
|
12
|
+
end
|
13
|
+
|
14
|
+
Remarkable.include_matchers!(Remarkable::ActiveRecord, RSpec::Core::ExampleGroup)
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module Remarkable
|
2
|
+
module ActiveRecord
|
3
|
+
module Matchers
|
4
|
+
class AcceptNestedAttributesForMatcher < Remarkable::ActiveRecord::Base #:nodoc:
|
5
|
+
arguments :collection => :associations, :as => :association
|
6
|
+
|
7
|
+
collection_assertions :association_exists?, :is_autosave?, :responds_to_attributes?,
|
8
|
+
:allows_destroy?, :accepts?, :rejects?
|
9
|
+
|
10
|
+
optionals :allow_destroy, :default => true
|
11
|
+
optionals :accept, :reject, :splat => true
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def association_exists?
|
16
|
+
reflection
|
17
|
+
end
|
18
|
+
|
19
|
+
def is_autosave?
|
20
|
+
reflection.options[:autosave] == true
|
21
|
+
end
|
22
|
+
|
23
|
+
def responds_to_attributes?
|
24
|
+
@subject.respond_to?(:"#{@association}_attributes=", true)
|
25
|
+
end
|
26
|
+
|
27
|
+
def allows_destroy?
|
28
|
+
return true unless @options.key?(:allow_destroy)
|
29
|
+
|
30
|
+
@subject.instance_eval <<-ALLOW_DESTROY
|
31
|
+
def assign_nested_attributes_for_#{reflection_type}_association(association, *args)
|
32
|
+
if self.respond_to?(:nested_attributes_options)
|
33
|
+
self.nested_attributes_options[association.to_sym][:allow_destroy]
|
34
|
+
else
|
35
|
+
args.last
|
36
|
+
end
|
37
|
+
end
|
38
|
+
ALLOW_DESTROY
|
39
|
+
|
40
|
+
actual = @subject.send(:"#{@association}_attributes=", {})
|
41
|
+
return actual == @options[:allow_destroy], :actual => actual
|
42
|
+
end
|
43
|
+
|
44
|
+
def accepts?
|
45
|
+
return true unless @options.key?(:accept)
|
46
|
+
|
47
|
+
[@options[:accept]].flatten.each do |attributes|
|
48
|
+
return false, :attributes => attributes.inspect if reject_if_proc.call(attributes)
|
49
|
+
end
|
50
|
+
|
51
|
+
true
|
52
|
+
end
|
53
|
+
|
54
|
+
def rejects?
|
55
|
+
return true unless @options.key?(:reject)
|
56
|
+
|
57
|
+
[@options[:reject]].flatten.each do |attributes|
|
58
|
+
return false, :attributes => attributes.inspect unless reject_if_proc.call(attributes)
|
59
|
+
end
|
60
|
+
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
private
|
65
|
+
|
66
|
+
def reflection
|
67
|
+
@reflection ||= subject_class.reflect_on_association(@association.to_sym)
|
68
|
+
end
|
69
|
+
|
70
|
+
def reflection_type
|
71
|
+
case reflection.macro
|
72
|
+
when :has_one, :belongs_to
|
73
|
+
:one_to_one
|
74
|
+
when :has_many, :has_and_belongs_to_many
|
75
|
+
:collection
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def reject_if_proc
|
80
|
+
if subject_class.respond_to?(:nested_attributes_options)
|
81
|
+
subject_class.nested_attributes_options[@association.to_sym][:reject_if]
|
82
|
+
else
|
83
|
+
subject_class.reject_new_nested_attributes_procs[@association.to_sym]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
# Ensures that the model accepts nested attributes for the given associations.
|
90
|
+
#
|
91
|
+
# == Options
|
92
|
+
#
|
93
|
+
# * <tt>allow_destroy</tt> - When true allows the association to be destroyed
|
94
|
+
# * <tt>accept</tt> - attributes that should be accepted by the :reject_if proc
|
95
|
+
# * <tt>reject</tt> - attributes that should be rejected by the :reject_if proc
|
96
|
+
#
|
97
|
+
# == Examples
|
98
|
+
#
|
99
|
+
# should_accept_nested_attributes_for :tasks
|
100
|
+
# should_accept_nested_attributes_for :tasks, :allow_destroy => true
|
101
|
+
#
|
102
|
+
# :accept and :reject takes objects that are verified against the proc. So
|
103
|
+
# having a model:
|
104
|
+
#
|
105
|
+
# class Projects < ActiveRecord::Base
|
106
|
+
# has_many :tasks
|
107
|
+
# accepts_nested_attributes_for :tasks, :reject_if => proc { |a| a[:title].blank? }
|
108
|
+
# end
|
109
|
+
#
|
110
|
+
# You can have the following specs:
|
111
|
+
#
|
112
|
+
# should_accept_nested_attributes_for :tasks, :reject => { :title => '' } # Passes
|
113
|
+
# should_accept_nested_attributes_for :tasks, :accept => { :title => 'My task' } # Passes
|
114
|
+
#
|
115
|
+
# should_accept_nested_attributes_for :tasks, :accept => { :title => 'My task' },
|
116
|
+
# :reject => { :title => '' } # Passes
|
117
|
+
#
|
118
|
+
# should_accept_nested_attributes_for :tasks, :accept => { :title => '' } # Fail
|
119
|
+
# should_accept_nested_attributes_for :tasks, :reject => { :title => 'My task' } # Fail
|
120
|
+
#
|
121
|
+
# You can also give arrays to :accept and :reject to verify multiple attributes.
|
122
|
+
# In such cases the block syntax is more recommended for readability:
|
123
|
+
#
|
124
|
+
# should_accept_nested_attributes_for :tasks do
|
125
|
+
# m.allow_destroy(false)
|
126
|
+
# m.accept :title => 'My task'
|
127
|
+
# m.accept :title => 'Another task'
|
128
|
+
# m.reject :title => nil
|
129
|
+
# m.reject :title => ''
|
130
|
+
# end
|
131
|
+
#
|
132
|
+
def accept_nested_attributes_for(*args, &block)
|
133
|
+
AcceptNestedAttributesForMatcher.new(*args, &block).spec(self)
|
134
|
+
end
|
135
|
+
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module Remarkable
|
2
|
+
module ActiveRecord
|
3
|
+
module Matchers
|
4
|
+
class AllowMassAssignmentOfMatcher < Remarkable::ActiveRecord::Base #:nodoc:
|
5
|
+
include Remarkable::Negative
|
6
|
+
arguments :collection => :attributes, :as => :attribute
|
7
|
+
|
8
|
+
assertion :allows?
|
9
|
+
collection_assertions :is_accessible?, :is_protected?
|
10
|
+
|
11
|
+
protected
|
12
|
+
|
13
|
+
# If no attribute is given, check if no attribute is being protected,
|
14
|
+
# otherwise it fails.
|
15
|
+
#
|
16
|
+
def allows?
|
17
|
+
return positive? unless @attributes.empty?
|
18
|
+
protected_attributes.nil? || protected_attributes.empty?
|
19
|
+
end
|
20
|
+
|
21
|
+
def is_accessible?
|
22
|
+
return positive? if accessible_attributes.nil?
|
23
|
+
accessible_attributes.include?(@attribute.to_s)
|
24
|
+
end
|
25
|
+
|
26
|
+
def is_protected?
|
27
|
+
return accessible_attributes.nil? || positive? if protected_attributes.nil?
|
28
|
+
!protected_attributes.include?(@attribute.to_s)
|
29
|
+
end
|
30
|
+
|
31
|
+
def interpolation_options
|
32
|
+
if @subject
|
33
|
+
if positive?
|
34
|
+
{ :protected_attributes => array_to_sentence((protected_attributes || []).to_a, false, '[]') }
|
35
|
+
else
|
36
|
+
{ :accessible_attributes => array_to_sentence((accessible_attributes || []).to_a, false, '[]') }
|
37
|
+
end
|
38
|
+
else
|
39
|
+
{}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def accessible_attributes
|
46
|
+
@accessible_attributes ||= unless subject_class.accessible_attributes.empty?
|
47
|
+
subject_class.accessible_attributes
|
48
|
+
else
|
49
|
+
subject_class.column_names - subject_class.protected_attributes.to_a
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def protected_attributes
|
54
|
+
@protected_attributes ||= if subject_class.accessible_attributes.empty?
|
55
|
+
subject_class.protected_attributes
|
56
|
+
else
|
57
|
+
subject_class.column_names - subject_class.accessible_attributes.to_a
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
# Ensures that the attribute can be set on mass update.
|
63
|
+
#
|
64
|
+
# == Examples
|
65
|
+
#
|
66
|
+
# should_allow_mass_assignment_of :email, :name
|
67
|
+
# it { should allow_mass_assignment_of(:email, :name) }
|
68
|
+
#
|
69
|
+
def allow_mass_assignment_of(*attributes, &block)
|
70
|
+
AllowMassAssignmentOfMatcher.new(*attributes, &block).spec(self)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|