shoulda-matchers 3.0.1 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (112) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +3 -3
  4. data/CONTRIBUTING.md +60 -28
  5. data/Gemfile +1 -0
  6. data/Gemfile.lock +15 -12
  7. data/NEWS.md +111 -0
  8. data/README.md +94 -6
  9. data/Rakefile +10 -8
  10. data/custom_plan.rb +88 -0
  11. data/gemfiles/4.0.0.gemfile +1 -0
  12. data/gemfiles/4.0.0.gemfile.lock +21 -18
  13. data/gemfiles/4.0.1.gemfile +1 -0
  14. data/gemfiles/4.0.1.gemfile.lock +21 -18
  15. data/gemfiles/4.1.gemfile +1 -0
  16. data/gemfiles/4.1.gemfile.lock +21 -18
  17. data/gemfiles/4.2.gemfile +1 -0
  18. data/gemfiles/4.2.gemfile.lock +24 -21
  19. data/lib/shoulda/matchers/action_controller/permit_matcher.rb +6 -11
  20. data/lib/shoulda/matchers/active_model.rb +10 -1
  21. data/lib/shoulda/matchers/active_model/allow_value_matcher.rb +258 -180
  22. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_changed_value_error.rb +45 -0
  23. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_does_not_exist_error.rb +23 -0
  24. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter.rb +236 -0
  25. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setter_and_validator.rb +62 -0
  26. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters.rb +40 -0
  27. data/lib/shoulda/matchers/active_model/allow_value_matcher/attribute_setters_and_validators.rb +48 -0
  28. data/lib/shoulda/matchers/active_model/allow_value_matcher/successful_check.rb +14 -0
  29. data/lib/shoulda/matchers/active_model/allow_value_matcher/successful_setting.rb +14 -0
  30. data/lib/shoulda/matchers/active_model/disallow_value_matcher.rb +34 -14
  31. data/lib/shoulda/matchers/active_model/helpers.rb +9 -17
  32. data/lib/shoulda/matchers/active_model/numericality_matchers/comparison_matcher.rb +13 -6
  33. data/lib/shoulda/matchers/active_model/numericality_matchers/even_number_matcher.rb +13 -2
  34. data/lib/shoulda/matchers/active_model/numericality_matchers/numeric_type_matcher.rb +19 -35
  35. data/lib/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher.rb +13 -2
  36. data/lib/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher.rb +12 -2
  37. data/lib/shoulda/matchers/active_model/qualifiers.rb +12 -0
  38. data/lib/shoulda/matchers/active_model/qualifiers/ignore_interference_by_writer.rb +101 -0
  39. data/lib/shoulda/matchers/active_model/qualifiers/ignoring_interference_by_writer.rb +21 -0
  40. data/lib/shoulda/matchers/active_model/validate_absence_of_matcher.rb +30 -32
  41. data/lib/shoulda/matchers/active_model/validate_acceptance_of_matcher.rb +5 -8
  42. data/lib/shoulda/matchers/active_model/validate_confirmation_of_matcher.rb +22 -22
  43. data/lib/shoulda/matchers/active_model/validate_exclusion_of_matcher.rb +27 -16
  44. data/lib/shoulda/matchers/active_model/validate_inclusion_of_matcher.rb +58 -15
  45. data/lib/shoulda/matchers/active_model/validate_length_of_matcher.rb +22 -12
  46. data/lib/shoulda/matchers/active_model/validate_numericality_of_matcher.rb +165 -87
  47. data/lib/shoulda/matchers/active_model/validate_presence_of_matcher.rb +7 -9
  48. data/lib/shoulda/matchers/active_model/validation_matcher.rb +111 -49
  49. data/lib/shoulda/matchers/active_model/validation_matcher/build_description.rb +60 -0
  50. data/lib/shoulda/matchers/active_model/validator.rb +71 -52
  51. data/lib/shoulda/matchers/active_record/define_enum_for_matcher.rb +19 -5
  52. data/lib/shoulda/matchers/active_record/validate_uniqueness_of_matcher.rb +450 -124
  53. data/lib/shoulda/matchers/util.rb +43 -0
  54. data/lib/shoulda/matchers/util/word_wrap.rb +59 -31
  55. data/lib/shoulda/matchers/version.rb +1 -1
  56. data/script/update_gem_in_all_appraisals +1 -1
  57. data/script/update_gems_in_all_appraisals +1 -1
  58. data/spec/acceptance/multiple_libraries_integration_spec.rb +5 -2
  59. data/spec/acceptance/rails_integration_spec.rb +6 -2
  60. data/spec/spec_helper.rb +1 -3
  61. data/spec/support/acceptance/helpers/step_helpers.rb +4 -1
  62. data/spec/support/tests/current_bundle.rb +21 -7
  63. data/spec/support/unit/active_record/create_table.rb +54 -0
  64. data/spec/support/unit/attribute.rb +47 -0
  65. data/spec/support/unit/capture.rb +6 -0
  66. data/spec/support/unit/change_value.rb +111 -0
  67. data/spec/support/unit/create_model_arguments/basic.rb +135 -0
  68. data/spec/support/unit/create_model_arguments/has_many.rb +15 -0
  69. data/spec/support/unit/create_model_arguments/uniqueness_matcher.rb +74 -0
  70. data/spec/support/unit/helpers/active_record_versions.rb +1 -1
  71. data/spec/support/unit/helpers/class_builder.rb +61 -47
  72. data/spec/support/unit/helpers/database_helpers.rb +5 -3
  73. data/spec/support/unit/helpers/model_builder.rb +77 -97
  74. data/spec/support/unit/helpers/validation_matcher_scenario_helpers.rb +44 -0
  75. data/spec/support/unit/load_environment.rb +12 -0
  76. data/spec/support/unit/matchers/fail_with_message_including_matcher.rb +2 -2
  77. data/spec/support/unit/matchers/fail_with_message_matcher.rb +12 -1
  78. data/spec/support/unit/model_creation_strategies/active_model.rb +111 -0
  79. data/spec/support/unit/model_creation_strategies/active_record.rb +77 -0
  80. data/spec/support/unit/model_creators.rb +19 -0
  81. data/spec/support/unit/model_creators/active_model.rb +39 -0
  82. data/spec/support/unit/model_creators/active_record.rb +43 -0
  83. data/spec/support/unit/model_creators/active_record/has_and_belongs_to_many.rb +95 -0
  84. data/spec/support/unit/model_creators/active_record/has_many.rb +67 -0
  85. data/spec/support/unit/model_creators/active_record/uniqueness_matcher.rb +42 -0
  86. data/spec/support/unit/model_creators/basic.rb +97 -0
  87. data/spec/support/unit/rails_application.rb +1 -1
  88. data/spec/support/unit/record_validating_confirmation_builder.rb +3 -7
  89. data/spec/support/unit/shared_examples/ignoring_interference_by_writer.rb +79 -0
  90. data/spec/support/unit/validation_matcher_scenario.rb +62 -0
  91. data/spec/unit/shoulda/matchers/active_model/allow_mass_assignment_of_matcher_spec.rb +4 -0
  92. data/spec/unit/shoulda/matchers/active_model/allow_value_matcher_spec.rb +575 -140
  93. data/spec/unit/shoulda/matchers/active_model/validate_absence_of_matcher_spec.rb +115 -15
  94. data/spec/unit/shoulda/matchers/active_model/validate_acceptance_of_matcher_spec.rb +42 -4
  95. data/spec/unit/shoulda/matchers/active_model/validate_confirmation_of_matcher_spec.rb +92 -6
  96. data/spec/unit/shoulda/matchers/active_model/validate_exclusion_of_matcher_spec.rb +122 -10
  97. data/spec/unit/shoulda/matchers/active_model/validate_inclusion_of_matcher_spec.rb +306 -58
  98. data/spec/unit/shoulda/matchers/active_model/validate_length_of_matcher_spec.rb +122 -3
  99. data/spec/unit/shoulda/matchers/active_model/validate_numericality_of_matcher_spec.rb +805 -131
  100. data/spec/unit/shoulda/matchers/active_model/validate_presence_of_matcher_spec.rb +196 -29
  101. data/spec/unit/shoulda/matchers/active_record/define_enum_for_matcher_spec.rb +82 -40
  102. data/spec/unit/shoulda/matchers/active_record/validate_uniqueness_of_matcher_spec.rb +600 -101
  103. data/spec/unit/shoulda/matchers/util/word_wrap_spec.rb +88 -33
  104. data/spec/unit_spec_helper.rb +10 -22
  105. data/zeus.json +11 -0
  106. metadata +64 -23
  107. data/lib/shoulda/matchers/active_model/strict_validator.rb +0 -51
  108. data/spec/support/unit/shared_examples/numerical_type_submatcher.rb +0 -15
  109. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/comparison_matcher_spec.rb +0 -288
  110. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/even_number_matcher_spec.rb +0 -100
  111. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/odd_number_matcher_spec.rb +0 -100
  112. data/spec/unit/shoulda/matchers/active_model/numericality_matchers/only_integer_matcher_spec.rb +0 -100
@@ -9,10 +9,12 @@ module UnitTests
9
9
  Tests::Database.instance.adapter_name
10
10
  end
11
11
 
12
- def database_supports_uuid_columns?
12
+ def postgresql?
13
13
  database_adapter == :postgresql
14
14
  end
15
- alias_method :database_supports_array_columns?,
16
- :database_supports_uuid_columns?
15
+
16
+ alias_method :database_supports_array_columns?, :postgresql?
17
+ alias_method :database_supports_uuid_columns?, :postgresql?
18
+ alias_method :database_supports_money_columns?, :postgresql?
17
19
  end
18
20
  end
@@ -2,133 +2,113 @@ require_relative 'class_builder'
2
2
 
3
3
  module UnitTests
4
4
  module ModelBuilder
5
- include ClassBuilder
6
-
7
- def self.configure_example_group(example_group)
8
- example_group.include(self)
9
-
10
- example_group.after do
11
- clear_column_caches
12
- drop_created_tables
13
- end
5
+ def create_table(*args, &block)
6
+ ModelBuilder.create_table(*args, &block)
14
7
  end
15
8
 
16
- def create_table(table_name, options = {}, &block)
17
- connection = ActiveRecord::Base.connection
18
-
19
- begin
20
- connection.execute("DROP TABLE IF EXISTS #{table_name}")
21
- connection.create_table(table_name, options, &block)
22
- created_tables << table_name
23
- connection
24
- rescue Exception => e
25
- connection.execute("DROP TABLE IF EXISTS #{table_name}")
26
- raise e
27
- end
9
+ def define_model(*args, &block)
10
+ ModelBuilder.define_model(*args, &block)
28
11
  end
29
12
 
30
- def define_model_class(class_name, &block)
31
- define_class(class_name, ActiveRecord::Base, &block)
13
+ def define_model_class(*args, &block)
14
+ ModelBuilder.define_model_class(*args, &block)
32
15
  end
33
16
 
34
- def define_active_model_class(class_name, options = {}, &block)
35
- accessors = options.fetch(:accessors, [])
36
-
37
- define_class(class_name) do
38
- include ActiveModel::Validations
17
+ def define_active_model_class(*args, &block)
18
+ ModelBuilder.define_active_model_class(*args, &block)
19
+ end
39
20
 
40
- def initialize(attributes = {})
41
- attributes.each do |name, value|
42
- __send__("#{name}=", value)
43
- end
44
- end
21
+ class << self
22
+ def configure_example_group(example_group)
23
+ example_group.include(self)
45
24
 
46
- accessors.each do |column|
47
- attr_accessor column.to_sym
25
+ example_group.after do
26
+ ModelBuilder.reset
48
27
  end
28
+ end
49
29
 
50
- if block_given?
51
- class_eval(&block)
52
- end
30
+ def reset
31
+ clear_column_caches
32
+ drop_created_tables
33
+ created_tables.clear
34
+ defined_models.clear
53
35
  end
54
- end
55
36
 
56
- def define_model(name, columns = {}, &block)
57
- class_name = name.to_s.pluralize.classify
58
- table_name = class_name.tableize.gsub('/', '_')
59
-
60
- table_block = lambda do |table|
61
- columns.each do |column_name, specification|
62
- if specification.is_a?(Hash)
63
- column_type = specification[:type]
64
- column_options = specification.fetch(:options, {})
65
- else
66
- column_type = specification
67
- column_options = {}
68
- end
69
-
70
- begin
71
- table.__send__(column_type, column_name, column_options)
72
- rescue NoMethodError
73
- raise NoMethodError, "#{Tests::Database.instance.adapter_class} does not support :#{column_type} columns"
74
- end
37
+ def create_table(table_name, options = {}, &block)
38
+ connection = ::ActiveRecord::Base.connection
39
+
40
+ begin
41
+ connection.execute("DROP TABLE IF EXISTS #{table_name}")
42
+ connection.create_table(table_name, options, &block)
43
+ created_tables << table_name
44
+ connection
45
+ rescue Exception => e
46
+ connection.execute("DROP TABLE IF EXISTS #{table_name}")
47
+ raise e
75
48
  end
76
49
  end
77
50
 
78
- if columns.key?(:id) && columns[:id] == false
79
- columns.delete(:id)
80
- create_table(table_name, id: false, &table_block)
81
- else
82
- create_table(table_name, &table_block)
51
+ def define_model_class(class_name, &block)
52
+ ClassBuilder.define_class(class_name, ::ActiveRecord::Base, &block)
83
53
  end
84
54
 
85
- model = define_model_class(class_name).tap do |m|
86
- if block
87
- if block.arity == 0
88
- m.class_eval(&block)
89
- else
90
- block.call(m)
91
- end
55
+ def define_active_model_class(class_name, options = {}, &block)
56
+ attribute_names = options.delete(:accessors) { [] }
57
+
58
+ columns = attribute_names.reduce({}) do |hash, attribute_name|
59
+ hash.merge(attribute_name => nil)
92
60
  end
93
61
 
94
- m.table_name = table_name
62
+ UnitTests::ModelCreationStrategies::ActiveModel.call(
63
+ 'Example',
64
+ columns,
65
+ options,
66
+ &block
67
+ )
95
68
  end
96
69
 
97
- defined_models << model
70
+ def define_model(name, columns = {}, options = {}, &block)
71
+ model = UnitTests::ModelCreationStrategies::ActiveRecord.call(
72
+ name,
73
+ columns,
74
+ options,
75
+ &block
76
+ )
77
+ defined_models << model
78
+ model
79
+ end
98
80
 
99
- model
100
- end
81
+ private
101
82
 
102
- private
83
+ def clear_column_caches
84
+ # Rails 4.x
85
+ if ::ActiveRecord::Base.connection.respond_to?(:schema_cache)
86
+ ::ActiveRecord::Base.connection.schema_cache.clear!
87
+ # Rails 3.1 - 4.0
88
+ elsif ::ActiveRecord::Base.connection_pool.respond_to?(:clear_cache!)
89
+ ::ActiveRecord::Base.connection_pool.clear_cache!
90
+ end
103
91
 
104
- def clear_column_caches
105
- # Rails 4.x
106
- if ActiveRecord::Base.connection.respond_to?(:schema_cache)
107
- ActiveRecord::Base.connection.schema_cache.clear!
108
- # Rails 3.1 - 4.0
109
- elsif ActiveRecord::Base.connection_pool.respond_to?(:clear_cache!)
110
- ActiveRecord::Base.connection_pool.clear_cache!
92
+ defined_models.each do |model|
93
+ model.reset_column_information
94
+ end
111
95
  end
112
96
 
113
- defined_models.each do |model|
114
- model.reset_column_information
115
- end
116
- end
97
+ def drop_created_tables
98
+ connection = ::ActiveRecord::Base.connection
117
99
 
118
- def drop_created_tables
119
- connection = ActiveRecord::Base.connection
120
-
121
- created_tables.each do |table_name|
122
- connection.execute("DROP TABLE IF EXISTS #{table_name}")
100
+ created_tables.each do |table_name|
101
+ connection.execute("DROP TABLE IF EXISTS #{table_name}")
102
+ end
123
103
  end
124
- end
125
104
 
126
- def created_tables
127
- @_created_tables ||= []
128
- end
105
+ def created_tables
106
+ @_created_tables ||= []
107
+ end
129
108
 
130
- def defined_models
131
- @_defined_models ||= []
109
+ def defined_models
110
+ @_defined_models ||= []
111
+ end
132
112
  end
133
113
  end
134
114
  end
@@ -0,0 +1,44 @@
1
+ module UnitTests
2
+ module ValidationMatcherScenarioHelpers
3
+ def self.configure_example_group(example_group)
4
+ example_group.include(self)
5
+ end
6
+
7
+ def build_scenario_for_validation_matcher(args)
8
+ UnitTests::ValidationMatcherScenario.new(
9
+ build_validation_matcher_scenario_args(args)
10
+ )
11
+ end
12
+
13
+ protected
14
+
15
+ def validation_matcher_scenario_args
16
+ {}
17
+ end
18
+
19
+ def configure_validation_matcher(matcher)
20
+ matcher
21
+ end
22
+
23
+ private
24
+
25
+ def build_validation_matcher_scenario_args(args)
26
+ args.
27
+ deep_merge(validation_matcher_scenario_args).
28
+ deep_merge(
29
+ matcher_name: matcher_name,
30
+ matcher_proc: method(matcher_name)
31
+ )
32
+ end
33
+
34
+ def matcher_name
35
+ validation_matcher_scenario_args.fetch(:matcher_name) do
36
+ raise KeyNotFoundError.new(<<-MESSAGE)
37
+ Please implement #validation_matcher_scenario_args in your example
38
+ group, in such a way that it returns a hash that contains a
39
+ :matcher_name key.
40
+ MESSAGE
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,12 @@
1
+ require_relative '../tests/current_bundle'
2
+ require_relative 'rails_application'
3
+
4
+ Tests::CurrentBundle.instance.assert_appraisal!
5
+
6
+ $test_app = UnitTests::RailsApplication.new
7
+ $test_app.create
8
+ $test_app.load
9
+
10
+ require 'active_record/base'
11
+
12
+ ENV['RAILS_ENV'] = 'test'
@@ -24,10 +24,10 @@ module UnitTests
24
24
  lines << Shoulda::Matchers::Util.indent(expected, 2)
25
25
 
26
26
  if @actual
27
- lines << 'Actually failed with:'
27
+ lines << 'The full message was:'
28
28
  lines << Shoulda::Matchers::Util.indent(@actual, 2)
29
29
  else
30
- lines << 'However, the expectation did not fail.'
30
+ lines << 'However, the expectation did not fail at all.'
31
31
  end
32
32
 
33
33
  lines.join("\n")
@@ -26,8 +26,13 @@ module UnitTests
26
26
  if @actual
27
27
  lines << 'Actually failed with:'
28
28
  lines << Shoulda::Matchers::Util.indent(@actual, 2)
29
+ lines << "Diff:"
30
+ lines << Shoulda::Matchers::Util.indent(
31
+ differ.diff(@actual, expected)[1..-1],
32
+ 2
33
+ )
29
34
  else
30
- lines << 'However, the expectation did not fail.'
35
+ lines << 'However, the expectation did not fail at all.'
31
36
  end
32
37
 
33
38
  lines.join("\n")
@@ -46,6 +51,12 @@ module UnitTests
46
51
  def failure_message_for_should_not
47
52
  failure_message_when_negated
48
53
  end
54
+
55
+ private
56
+
57
+ def differ
58
+ @_differ ||= RSpec::Support::Differ.new
59
+ end
49
60
  end
50
61
  end
51
62
  end
@@ -0,0 +1,111 @@
1
+ module UnitTests
2
+ module ModelCreationStrategies
3
+ class ActiveModel
4
+ def self.call(name, columns = {}, options = {}, &block)
5
+ new(name, columns, options, &block).call
6
+ end
7
+
8
+ def initialize(name, columns = {}, options = {}, &block)
9
+ @name = name
10
+ @columns = columns
11
+ @options = options
12
+ @model_customizers = []
13
+
14
+ if block
15
+ customize_model(&block)
16
+ end
17
+ end
18
+
19
+ def customize_model(&block)
20
+ model_customizers << block
21
+ end
22
+
23
+ def call
24
+ ClassBuilder.define_class(name, Model).tap do |model|
25
+ model.columns = columns.keys
26
+
27
+ model_customizers.each do |block|
28
+ run_block(model, block)
29
+ end
30
+ end
31
+ end
32
+
33
+ protected
34
+
35
+ attr_reader :name, :columns, :model_customizers, :options
36
+
37
+ private
38
+
39
+ def run_block(model, block)
40
+ if block
41
+ if block.arity == 0
42
+ model.class_eval(&block)
43
+ else
44
+ block.call(model)
45
+ end
46
+ end
47
+ end
48
+
49
+ class Model
50
+ class << self
51
+ def columns
52
+ @_columns ||= []
53
+ end
54
+
55
+ def columns=(columns)
56
+ existing_columns = self.columns
57
+ new_columns = columns - existing_columns
58
+
59
+ @_columns += new_columns
60
+
61
+ include attributes_module
62
+
63
+ attributes_module.module_eval do
64
+ new_columns.each do |column|
65
+ define_method(column) do
66
+ attributes[column]
67
+ end
68
+
69
+ define_method("#{column}=") do |value|
70
+ attributes[column] = value
71
+ end
72
+ end
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def attributes_module
79
+ @_attributes_module ||= Module.new
80
+ end
81
+ end
82
+
83
+ include ::ActiveModel::Model
84
+
85
+ attr_reader :attributes
86
+
87
+ def initialize(attributes = {})
88
+ @attributes = attributes.symbolize_keys
89
+ end
90
+
91
+ def inspect
92
+ middle = '%s:0x%014x%s' % [
93
+ self.class,
94
+ object_id * 2,
95
+ ' ' + inspected_attributes.join(' ')
96
+ ]
97
+
98
+ "#<#{middle.strip}>"
99
+ end
100
+
101
+ private
102
+
103
+ def inspected_attributes
104
+ self.class.columns.map do |key, value|
105
+ "#{key}: #{attributes[key].inspect}"
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,77 @@
1
+ module UnitTests
2
+ module ModelCreationStrategies
3
+ class ActiveRecord
4
+ def self.call(name, columns = {}, options = {}, &block)
5
+ new(name, columns, options, &block).call
6
+ end
7
+
8
+ def initialize(name, columns = {}, options = {}, &block)
9
+ @name = name
10
+ @columns = columns
11
+ @options = options
12
+ @model_customizers = []
13
+
14
+ if block
15
+ customize_model(&block)
16
+ end
17
+ end
18
+
19
+ def customize_model(&block)
20
+ model_customizers << block
21
+ end
22
+
23
+ def call
24
+ create_table_for_model
25
+ define_class_for_model
26
+ end
27
+
28
+ protected
29
+
30
+ attr_reader :columns, :model_customizers, :name, :options
31
+
32
+ private
33
+
34
+ def create_table_for_model
35
+ UnitTests::ActiveRecord::CreateTable.call(table_name, columns)
36
+ end
37
+
38
+ def define_class_for_model
39
+ model = UnitTests::ModelBuilder.define_model_class(class_name)
40
+
41
+ model_customizers.each do |block|
42
+ run_block(model, block)
43
+ end
44
+
45
+ if whitelist_attributes?
46
+ model.attr_accessible(*columns.keys)
47
+ end
48
+
49
+ model.table_name = table_name
50
+
51
+ model
52
+ end
53
+
54
+ def run_block(model, block)
55
+ if block
56
+ if block.arity == 0
57
+ model.class_eval(&block)
58
+ else
59
+ block.call(model)
60
+ end
61
+ end
62
+ end
63
+
64
+ def class_name
65
+ name.to_s.pluralize.classify
66
+ end
67
+
68
+ def table_name
69
+ class_name.tableize.gsub('/', '_')
70
+ end
71
+
72
+ def whitelist_attributes?
73
+ options.fetch(:whitelist_attributes, true)
74
+ end
75
+ end
76
+ end
77
+ end