toolchain 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +5 -0
- data/.rspec +1 -0
- data/Gemfile +10 -0
- data/Gemfile.lock +34 -0
- data/LICENSE +22 -0
- data/README.md +254 -0
- data/Rakefile +1 -0
- data/lib/toolchain.rb +2 -0
- data/lib/toolchain/attributes.rb +154 -0
- data/lib/toolchain/attributes/configuration.rb +41 -0
- data/lib/toolchain/attributes/errors.rb +5 -0
- data/lib/toolchain/attributes/errors/invalid_hash_transformation.rb +4 -0
- data/lib/toolchain/attributes/errors/invalid_mass_assignment.rb +4 -0
- data/lib/toolchain/attributes/errors/type_mismatch.rb +4 -0
- data/lib/toolchain/attributes/ext/boolean.rb +4 -0
- data/lib/toolchain/attributes/helpers.rb +72 -0
- data/lib/toolchain/validations.rb +103 -0
- data/lib/toolchain/validations/delegation.rb +31 -0
- data/lib/toolchain/validations/delegator.rb +51 -0
- data/lib/toolchain/validations/helpers.rb +58 -0
- data/lib/toolchain/validations/validation_errors.rb +82 -0
- data/lib/toolchain/validations/validators.rb +12 -0
- data/lib/toolchain/validations/validators/acceptance.rb +25 -0
- data/lib/toolchain/validations/validators/base.rb +54 -0
- data/lib/toolchain/validations/validators/confirmation.rb +39 -0
- data/lib/toolchain/validations/validators/email.rb +26 -0
- data/lib/toolchain/validations/validators/exclusion.rb +29 -0
- data/lib/toolchain/validations/validators/format.rb +25 -0
- data/lib/toolchain/validations/validators/inclusion.rb +29 -0
- data/lib/toolchain/validations/validators/length.rb +60 -0
- data/lib/toolchain/validations/validators/presence.rb +25 -0
- data/lib/toolchain/version.rb +3 -0
- data/spec/spec_helper.rb +11 -0
- data/spec/toolchain/attributes/attribute_spec.rb +47 -0
- data/spec/toolchain/attributes/attributes_spec.rb +193 -0
- data/spec/toolchain/attributes/base_helper.rb +37 -0
- data/spec/toolchain/attributes/boolean_spec.rb +38 -0
- data/spec/toolchain/attributes/configuration_spec.rb +33 -0
- data/spec/toolchain/attributes/date_time_spec.rb +21 -0
- data/spec/toolchain/attributes/hash_spec.rb +61 -0
- data/spec/toolchain/attributes/include_attributes_spec.rb +19 -0
- data/spec/toolchain/attributes/initializer_spec.rb +32 -0
- data/spec/toolchain/validations/base_helper.rb +2 -0
- data/spec/toolchain/validations/custom_validations_spec.rb +26 -0
- data/spec/toolchain/validations/delegation_spec.rb +70 -0
- data/spec/toolchain/validations/include_validations_spec.rb +20 -0
- data/spec/toolchain/validations/inheritence_spec.rb +26 -0
- data/spec/toolchain/validations/multiple_validations_spec.rb +19 -0
- data/spec/toolchain/validations/nested_validations_spec.rb +68 -0
- data/spec/toolchain/validations/validation_errors_spec.rb +9 -0
- data/spec/toolchain/validations/validators/acceptance_spec.rb +48 -0
- data/spec/toolchain/validations/validators/confirmation_spec.rb +86 -0
- data/spec/toolchain/validations/validators/email_spec.rb +41 -0
- data/spec/toolchain/validations/validators/exclusion_spec.rb +53 -0
- data/spec/toolchain/validations/validators/format_spec.rb +44 -0
- data/spec/toolchain/validations/validators/inclusion_spec.rb +50 -0
- data/spec/toolchain/validations/validators/length_spec.rb +134 -0
- data/spec/toolchain/validations/validators/presence_spec.rb +34 -0
- data/toolchain.gemspec +21 -0
- metadata +161 -0
@@ -0,0 +1,12 @@
|
|
1
|
+
module Toolchain::Validations::Validators
|
2
|
+
require_relative "validators/base"
|
3
|
+
|
4
|
+
require_relative "validators/acceptance"
|
5
|
+
require_relative "validators/confirmation"
|
6
|
+
require_relative "validators/email"
|
7
|
+
require_relative "validators/exclusion"
|
8
|
+
require_relative "validators/format"
|
9
|
+
require_relative "validators/inclusion"
|
10
|
+
require_relative "validators/length"
|
11
|
+
require_relative "validators/presence"
|
12
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Toolchain::Validations::Validators
|
2
|
+
|
3
|
+
# Validates the acceptance of an attribute.
|
4
|
+
# Accepted values are as follows: `true`, `1` and `"1"`.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# class User::Creator
|
8
|
+
# validates :terms, acceptance: {
|
9
|
+
# message: "the terms of service must be accepted"
|
10
|
+
# }
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
class Acceptance < Base
|
14
|
+
|
15
|
+
def validate
|
16
|
+
errors.add(key_path, message || "must be accepted") if not_accepted?
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def not_accepted?
|
22
|
+
![1, "1", true].include?(value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
class Toolchain::Validations::Validators::Base
|
2
|
+
|
3
|
+
# @return [Object] the object that contains the attribute
|
4
|
+
# that'll be validated.
|
5
|
+
#
|
6
|
+
attr_reader :object
|
7
|
+
|
8
|
+
# @return [Toolchain::Validations::ValidationErrors] the errors object
|
9
|
+
# of the object that's being validated.
|
10
|
+
#
|
11
|
+
attr_reader :errors
|
12
|
+
|
13
|
+
# @return [Symbol] The key_path of the attribute that's being validated.
|
14
|
+
#
|
15
|
+
attr_reader :key_path
|
16
|
+
|
17
|
+
# @return [Hash] The value that was passed in to the validator
|
18
|
+
# at definition time. i.e. a Hash containing the regular expression
|
19
|
+
# for Toolchain::Validations::Validators::Formatter along with a message.
|
20
|
+
#
|
21
|
+
attr_reader :data
|
22
|
+
|
23
|
+
# @return [String] A custom message to override the
|
24
|
+
# default message with in case the attribute is invalid.
|
25
|
+
#
|
26
|
+
attr_reader :message
|
27
|
+
|
28
|
+
# Instantiates a new Toolchain::Validations::Validators object
|
29
|
+
# which'll be used to validate the target object.
|
30
|
+
#
|
31
|
+
# @param object [Object]
|
32
|
+
# @param key_path [Object]
|
33
|
+
# @param data [Object]
|
34
|
+
#
|
35
|
+
def initialize(object, key_path, data)
|
36
|
+
@object = object
|
37
|
+
@errors = object.errors
|
38
|
+
@key_path = key_path
|
39
|
+
@data = data
|
40
|
+
@message = data[:message] if data.is_a?(Hash)
|
41
|
+
end
|
42
|
+
|
43
|
+
# @return [Object] The value that's stored in the attribute of
|
44
|
+
# the object that's being validated.
|
45
|
+
#
|
46
|
+
def value
|
47
|
+
@value ||= (
|
48
|
+
keys = key_path.dup
|
49
|
+
keys.inject(object.send(keys.shift)) do |memo, key|
|
50
|
+
memo[key] if memo.kind_of?(Hash)
|
51
|
+
end
|
52
|
+
)
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Toolchain::Validations::Validators
|
2
|
+
|
3
|
+
# Validates the confirmation of an attribute.
|
4
|
+
# In the example both `password` and `password_confirmation`
|
5
|
+
# attributes must match. One or more `nil` values will result in the
|
6
|
+
# validation error being triggered as well.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# class User::Creator
|
10
|
+
# validates :password, confirmation: {
|
11
|
+
# message: "doesn't match confirmation"
|
12
|
+
# }
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
class Confirmation < Base
|
16
|
+
|
17
|
+
def validate
|
18
|
+
if no_match?
|
19
|
+
errors.add(key_path, message || "doesn't match confirmation")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def no_match?
|
26
|
+
value.nil? || confirmation.nil? || value != confirmation
|
27
|
+
end
|
28
|
+
|
29
|
+
def confirmation
|
30
|
+
@confirmation ||= (
|
31
|
+
keys = key_path.dup
|
32
|
+
keys << :"#{keys.pop}_confirmation"
|
33
|
+
keys.inject(object.send(keys.shift)) do |memo, key|
|
34
|
+
memo[key] if memo.kind_of?(Hash)
|
35
|
+
end
|
36
|
+
)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Toolchain::Validations::Validators
|
2
|
+
|
3
|
+
# Validates the format of an email address.
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# class User::Creator
|
7
|
+
# validates :email, email: {
|
8
|
+
# message: "isn't valid"
|
9
|
+
# }
|
10
|
+
# end
|
11
|
+
#
|
12
|
+
class Email < Base
|
13
|
+
|
14
|
+
PATTERN = /\A[^@\s]+@([^@\s]+\.)+[^@\s]+\z/
|
15
|
+
|
16
|
+
def validate
|
17
|
+
errors.add(key_path, message || "is invalid") if no_email?
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def no_email?
|
23
|
+
value.nil? || !value.match(PATTERN)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Toolchain::Validations::Validators
|
2
|
+
|
3
|
+
# Validates the exclusion of values in an attribute.
|
4
|
+
# In the example only games without a pegi rating
|
5
|
+
# of 12, 16, 18 are valid.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# class Game::Creator
|
9
|
+
# validates :pegi, exclusion: {
|
10
|
+
# in: [12, 16, 18],
|
11
|
+
# message: "invalid pegi rating"
|
12
|
+
# }
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
class Exclusion < Base
|
16
|
+
|
17
|
+
def validate
|
18
|
+
if included?
|
19
|
+
errors.add(key_path, message || "is invalid")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def included?
|
26
|
+
data[:in].include?(value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Toolchain::Validations::Validators
|
2
|
+
|
3
|
+
# Validates the format of an attribute using a regular expression.
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# class Company::Creator
|
7
|
+
# validates :credit_card, format: {
|
8
|
+
# with: /^\d+{4}-$\d+{4}-\d+{4}-\d+{4}/,
|
9
|
+
# message: "invalid credit card format"
|
10
|
+
# }
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
class Format < Base
|
14
|
+
|
15
|
+
def validate
|
16
|
+
errors.add(key_path, message || "is invalid") if no_match?
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def no_match?
|
22
|
+
value.nil? || !value.match(data[:with])
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Toolchain::Validations::Validators
|
2
|
+
|
3
|
+
# Validates the inclusion of values in an attribute.
|
4
|
+
# In the example, only `pending` and `dispatched` are
|
5
|
+
# allowed to be set.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# class Shipment::Creator
|
9
|
+
# validates :status, inclusion: {
|
10
|
+
# in: ["pending", "dispatched"],
|
11
|
+
# message: "available options are: pending, dispatched"
|
12
|
+
# }
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
class Inclusion < Base
|
16
|
+
|
17
|
+
def validate
|
18
|
+
if not_included?
|
19
|
+
errors.add(key_path, message || "is invalid")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def not_included?
|
26
|
+
!data.include?(value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Toolchain::Validations::Validators
|
2
|
+
|
3
|
+
# Validates the lengt of an attribute.
|
4
|
+
#
|
5
|
+
# @example
|
6
|
+
# class User::Creator
|
7
|
+
# validates :password, length: {
|
8
|
+
# between: 5..100,
|
9
|
+
# message: "must be between 5 and 100 characters long"
|
10
|
+
# }
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# class User::Creator
|
14
|
+
# validates :password, length: {
|
15
|
+
# greater_than: 5,
|
16
|
+
# less_than 100,
|
17
|
+
# message: "must be between 5 and 100 characters long"
|
18
|
+
# }
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
class Length < Base
|
22
|
+
|
23
|
+
def validate
|
24
|
+
errors.add(key_path, message || "is invalid") unless valid?
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def valid?
|
30
|
+
val =
|
31
|
+
if value.kind_of?(String) && value =~ /^\d+$/
|
32
|
+
value.to_i
|
33
|
+
elsif value.kind_of?(String) && value =~ /^\d+\.\d+$/
|
34
|
+
value.to_f
|
35
|
+
elsif value.kind_of?(String)
|
36
|
+
value.length
|
37
|
+
else
|
38
|
+
value
|
39
|
+
end
|
40
|
+
|
41
|
+
if data[:between]
|
42
|
+
return data[:between].include?(val)
|
43
|
+
end
|
44
|
+
|
45
|
+
if data[:greater_than] && data[:less_than]
|
46
|
+
return val > data[:greater_than] && val < data[:less_than]
|
47
|
+
end
|
48
|
+
|
49
|
+
if data[:greater_than]
|
50
|
+
return val > data[:greater_than]
|
51
|
+
end
|
52
|
+
|
53
|
+
if data[:less_than]
|
54
|
+
return val < data[:less_than]
|
55
|
+
end
|
56
|
+
|
57
|
+
false
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Toolchain::Validations::Validators
|
2
|
+
|
3
|
+
# Validates the presence of an attribute. If the attribute
|
4
|
+
# is either `nil` or `""` (empty String) it is considered invalid.
|
5
|
+
#
|
6
|
+
# @example
|
7
|
+
# class User::Creator
|
8
|
+
# validates :name, presence: {
|
9
|
+
# message: "is required"
|
10
|
+
# }
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
class Presence < Base
|
14
|
+
|
15
|
+
def validate
|
16
|
+
errors.add(key_path, message || "can't be blank") if blank?
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def blank?
|
22
|
+
[nil, ""].include?(value)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
require_relative "base_helper"
|
2
|
+
|
3
|
+
describe Toolchain::Attributes, "Attribute" do
|
4
|
+
|
5
|
+
let(:model) { ModelData.new }
|
6
|
+
|
7
|
+
it "should be nil by default" do
|
8
|
+
model.string.should == nil
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should be empty by default" do
|
12
|
+
model.string_default.should == ""
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should set a new String" do
|
16
|
+
expect { model.string = "Example" }.
|
17
|
+
to change { model.string }.from(nil).to("Example")
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should set to nil, resulting in default" do
|
21
|
+
model.string_default = "Example"
|
22
|
+
expect { model.string_default = nil }.
|
23
|
+
to change { model.string_default }.from("Example").to("")
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should instance-variable cache the result" do
|
27
|
+
model.time_default.should == model.time_default
|
28
|
+
end
|
29
|
+
|
30
|
+
it "requires the type to match the configured type" do
|
31
|
+
expect { model.string = 0 }.to raise_error(
|
32
|
+
Toolchain::Attributes::Errors::TypeMismatch,
|
33
|
+
"ModelData#string expected String type, but received Fixnum (0).")
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should not allow defaults of other data-type" do
|
37
|
+
expect {
|
38
|
+
class InvalidModelData
|
39
|
+
include Toolchain::Attributes
|
40
|
+
attribute :string, String, 0
|
41
|
+
end
|
42
|
+
}.to raise_error(
|
43
|
+
Toolchain::Attributes::Errors::TypeMismatch,
|
44
|
+
"expected InvalidModelData#string to have default value "+
|
45
|
+
"of String type, but received Fixnum (0).")
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,193 @@
|
|
1
|
+
require_relative "base_helper"
|
2
|
+
|
3
|
+
describe Toolchain::Attributes, "Attributes (Method)" do
|
4
|
+
|
5
|
+
let(:model) { ModelData.new }
|
6
|
+
|
7
|
+
def expect_date_time
|
8
|
+
[
|
9
|
+
Date.today.tap { |d| Date.stubs(:today).returns(d) },
|
10
|
+
Time.now.tap { |t| Time.stubs(:now).returns(t) },
|
11
|
+
DateTime.now.tap { |dt| DateTime.stubs(:now).returns(dt) }
|
12
|
+
]
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return attributes with Symbol keys" do
|
16
|
+
date, time, date_time = expect_date_time
|
17
|
+
|
18
|
+
model.attributes.should == {
|
19
|
+
array_default: [],
|
20
|
+
boolean_default: false,
|
21
|
+
float_default: 0.0,
|
22
|
+
hash_default: {},
|
23
|
+
integer_default: 0,
|
24
|
+
string_default: "",
|
25
|
+
date_default: date,
|
26
|
+
time_default: time,
|
27
|
+
date_time_default: date_time
|
28
|
+
}
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should return attributes with String keys" do
|
32
|
+
Toolchain::Attributes::Configuration.
|
33
|
+
hash_transformation = :stringify_keys
|
34
|
+
|
35
|
+
date, time, date_time = expect_date_time
|
36
|
+
|
37
|
+
model.attributes.should == {
|
38
|
+
"array_default" => [],
|
39
|
+
"boolean_default" => false,
|
40
|
+
"float_default" => 0.0,
|
41
|
+
"hash_default" => {},
|
42
|
+
"integer_default" => 0,
|
43
|
+
"string_default" => "",
|
44
|
+
"date_default" => date,
|
45
|
+
"time_default" => time,
|
46
|
+
"date_time_default" => date_time
|
47
|
+
}
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should symbolize hash, hash_default" do
|
51
|
+
model.hash = { "key" => { "value" => true } }
|
52
|
+
model.hash_default = { "key" => { "value" => true } }
|
53
|
+
model.attributes.tap do |attrs|
|
54
|
+
attrs[:hash].should == { key: { value: true } }
|
55
|
+
attrs[:hash_default].should == { key: { value: true } }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should stringify hash, hash_default" do
|
60
|
+
Toolchain::Attributes::Configuration.
|
61
|
+
hash_transformation = :stringify_keys
|
62
|
+
|
63
|
+
model.hash = { key: { value: true } }
|
64
|
+
model.hash_default = { key: { value: true } }
|
65
|
+
model.attributes.tap do |attrs|
|
66
|
+
attrs["hash"].should == { "key" => { "value" => true } }
|
67
|
+
attrs["hash_default"].should == { "key" => { "value" => true } }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should include nil attributes" do
|
72
|
+
Toolchain::Attributes::Configuration.
|
73
|
+
include_nil_in_attributes = true
|
74
|
+
|
75
|
+
date, time, date_time = expect_date_time
|
76
|
+
|
77
|
+
model.attributes.should == {
|
78
|
+
array: nil,
|
79
|
+
array_default: [],
|
80
|
+
boolean: nil,
|
81
|
+
boolean_default: false,
|
82
|
+
float: nil,
|
83
|
+
float_default: 0.0,
|
84
|
+
hash: nil,
|
85
|
+
hash_default: {},
|
86
|
+
integer: nil,
|
87
|
+
integer_default: 0,
|
88
|
+
string: nil,
|
89
|
+
string_default: "",
|
90
|
+
date: nil,
|
91
|
+
date_default: date,
|
92
|
+
time: nil,
|
93
|
+
time_default: time,
|
94
|
+
date_time: nil,
|
95
|
+
date_time_default: date_time
|
96
|
+
}
|
97
|
+
end
|
98
|
+
|
99
|
+
it "should mass-assign attributes" do
|
100
|
+
date, time, date_time = expect_date_time
|
101
|
+
|
102
|
+
model.attributes = {
|
103
|
+
string: "Example",
|
104
|
+
integer: 123,
|
105
|
+
float: 1.23,
|
106
|
+
hash: { foo: "bar" },
|
107
|
+
array: [1, 2, 3],
|
108
|
+
boolean: true,
|
109
|
+
date: date,
|
110
|
+
date_default: date,
|
111
|
+
time: time,
|
112
|
+
time_default: time,
|
113
|
+
date_time: date_time,
|
114
|
+
date_time_default: date_time,
|
115
|
+
}
|
116
|
+
|
117
|
+
model.attributes.should == {
|
118
|
+
array: [1, 2, 3],
|
119
|
+
array_default: [],
|
120
|
+
boolean: true,
|
121
|
+
boolean_default: false,
|
122
|
+
float: 1.23,
|
123
|
+
float_default: 0.0,
|
124
|
+
hash: { foo: "bar" },
|
125
|
+
hash_default: {},
|
126
|
+
integer: 123,
|
127
|
+
integer_default: 0,
|
128
|
+
string: "Example",
|
129
|
+
string_default: "",
|
130
|
+
date: date,
|
131
|
+
date_default: date,
|
132
|
+
time: time,
|
133
|
+
time_default: time,
|
134
|
+
date_time: date_time,
|
135
|
+
date_time_default: date_time
|
136
|
+
}
|
137
|
+
end
|
138
|
+
|
139
|
+
it "should not assign undefined attributes" do
|
140
|
+
date, time, date_time = expect_date_time
|
141
|
+
model.attributes = { unknown_attribute: true }
|
142
|
+
model.attributes.should == {
|
143
|
+
array_default: [],
|
144
|
+
boolean_default: false,
|
145
|
+
float_default: 0.0,
|
146
|
+
hash_default: {},
|
147
|
+
integer_default: 0,
|
148
|
+
string_default: "",
|
149
|
+
date_default: date,
|
150
|
+
time_default: time,
|
151
|
+
date_time_default: date_time,
|
152
|
+
}
|
153
|
+
end
|
154
|
+
|
155
|
+
it "should raise an exception non-Hash type is passed" do
|
156
|
+
expect { model.attributes = 0 }.
|
157
|
+
to raise_error(
|
158
|
+
Toolchain::Attributes::Errors::InvalidMassAssignment,
|
159
|
+
"Can't mass-assign Fixnum (0) type to ModelData#attributes.")
|
160
|
+
end
|
161
|
+
|
162
|
+
class InheritedModelData < ModelData
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should inherit all attribute definitions" do
|
166
|
+
date, time, date_time = expect_date_time
|
167
|
+
InheritedModelData.new.attributes.should == {
|
168
|
+
array_default: [],
|
169
|
+
boolean_default: false,
|
170
|
+
float_default: 0.0,
|
171
|
+
hash_default: {},
|
172
|
+
integer_default: 0,
|
173
|
+
string_default: "",
|
174
|
+
date_default: date,
|
175
|
+
time_default: time,
|
176
|
+
date_time_default: date_time
|
177
|
+
}
|
178
|
+
end
|
179
|
+
|
180
|
+
it "should mass-assign superclass keys" do
|
181
|
+
date, time, date_time = expect_date_time
|
182
|
+
model = InheritedModelData.new
|
183
|
+
model.attributes = { string: "Michael" }
|
184
|
+
model.string.should == "Michael"
|
185
|
+
end
|
186
|
+
|
187
|
+
it "should mass-assing superclass string keys" do
|
188
|
+
date, time, date_time = expect_date_time
|
189
|
+
model = InheritedModelData.new
|
190
|
+
model.attributes = { "string" => "Michael" }
|
191
|
+
model.string.should == "Michael"
|
192
|
+
end
|
193
|
+
end
|