ardm 0.0.1
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 +15 -0
- data/.gitignore +35 -0
- data/Gemfile +13 -0
- data/LICENSE +21 -0
- data/README.md +70 -0
- data/Rakefile +4 -0
- data/ardm.gemspec +29 -0
- data/db/.gitignore +1 -0
- data/lib/ardm/active_record/associations.rb +80 -0
- data/lib/ardm/active_record/base.rb +49 -0
- data/lib/ardm/active_record/dirty.rb +25 -0
- data/lib/ardm/active_record/hooks.rb +31 -0
- data/lib/ardm/active_record/inheritance.rb +37 -0
- data/lib/ardm/active_record/is/state_machine.rb +21 -0
- data/lib/ardm/active_record/is.rb +22 -0
- data/lib/ardm/active_record/not_found.rb +7 -0
- data/lib/ardm/active_record/predicate_builder/array_handler.rb +31 -0
- data/lib/ardm/active_record/predicate_builder/rails3.rb +147 -0
- data/lib/ardm/active_record/predicate_builder/rails4.rb +139 -0
- data/lib/ardm/active_record/predicate_builder/relation_handler.rb +15 -0
- data/lib/ardm/active_record/predicate_builder.rb +19 -0
- data/lib/ardm/active_record/property.rb +357 -0
- data/lib/ardm/active_record/query.rb +108 -0
- data/lib/ardm/active_record/record.rb +70 -0
- data/lib/ardm/active_record/relation.rb +83 -0
- data/lib/ardm/active_record/repository.rb +38 -0
- data/lib/ardm/active_record/serialization.rb +164 -0
- data/lib/ardm/active_record/storage_names.rb +28 -0
- data/lib/ardm/active_record/validations.rb +111 -0
- data/lib/ardm/active_record.rb +43 -0
- data/lib/ardm/data_mapper/not_found.rb +5 -0
- data/lib/ardm/data_mapper/record.rb +41 -0
- data/lib/ardm/data_mapper.rb +5 -0
- data/lib/ardm/env.rb +5 -0
- data/lib/ardm/property/api_key.rb +30 -0
- data/lib/ardm/property/bcrypt_hash.rb +31 -0
- data/lib/ardm/property/binary.rb +23 -0
- data/lib/ardm/property/boolean.rb +29 -0
- data/lib/ardm/property/class.rb +19 -0
- data/lib/ardm/property/comma_separated_list.rb +28 -0
- data/lib/ardm/property/csv.rb +35 -0
- data/lib/ardm/property/date.rb +12 -0
- data/lib/ardm/property/datetime.rb +12 -0
- data/lib/ardm/property/decimal.rb +38 -0
- data/lib/ardm/property/discriminator.rb +65 -0
- data/lib/ardm/property/enum.rb +51 -0
- data/lib/ardm/property/epoch_time.rb +38 -0
- data/lib/ardm/property/file_path.rb +25 -0
- data/lib/ardm/property/flag.rb +65 -0
- data/lib/ardm/property/float.rb +18 -0
- data/lib/ardm/property/integer.rb +24 -0
- data/lib/ardm/property/invalid_value_error.rb +22 -0
- data/lib/ardm/property/ip_address.rb +35 -0
- data/lib/ardm/property/json.rb +49 -0
- data/lib/ardm/property/lookup.rb +29 -0
- data/lib/ardm/property/numeric.rb +40 -0
- data/lib/ardm/property/object.rb +36 -0
- data/lib/ardm/property/paranoid_boolean.rb +18 -0
- data/lib/ardm/property/paranoid_datetime.rb +17 -0
- data/lib/ardm/property/regexp.rb +22 -0
- data/lib/ardm/property/serial.rb +16 -0
- data/lib/ardm/property/slug.rb +29 -0
- data/lib/ardm/property/string.rb +40 -0
- data/lib/ardm/property/support/dirty_minder.rb +169 -0
- data/lib/ardm/property/support/flags.rb +41 -0
- data/lib/ardm/property/support/paranoid_base.rb +78 -0
- data/lib/ardm/property/text.rb +11 -0
- data/lib/ardm/property/time.rb +12 -0
- data/lib/ardm/property/uri.rb +27 -0
- data/lib/ardm/property/uuid.rb +65 -0
- data/lib/ardm/property/validation.rb +208 -0
- data/lib/ardm/property/yaml.rb +38 -0
- data/lib/ardm/property.rb +891 -0
- data/lib/ardm/property_set.rb +152 -0
- data/lib/ardm/query/expression.rb +85 -0
- data/lib/ardm/query/ext/symbol.rb +37 -0
- data/lib/ardm/query/operator.rb +64 -0
- data/lib/ardm/record.rb +1 -0
- data/lib/ardm/support/assertions.rb +8 -0
- data/lib/ardm/support/deprecate.rb +12 -0
- data/lib/ardm/support/descendant_set.rb +89 -0
- data/lib/ardm/support/equalizer.rb +48 -0
- data/lib/ardm/support/ext/array.rb +22 -0
- data/lib/ardm/support/ext/blank.rb +25 -0
- data/lib/ardm/support/ext/hash.rb +67 -0
- data/lib/ardm/support/ext/module.rb +47 -0
- data/lib/ardm/support/ext/object.rb +57 -0
- data/lib/ardm/support/ext/string.rb +24 -0
- data/lib/ardm/support/ext/try_dup.rb +12 -0
- data/lib/ardm/support/hook.rb +405 -0
- data/lib/ardm/support/lazy_array.rb +451 -0
- data/lib/ardm/support/local_object_space.rb +13 -0
- data/lib/ardm/support/logger.rb +201 -0
- data/lib/ardm/support/mash.rb +176 -0
- data/lib/ardm/support/naming_conventions.rb +90 -0
- data/lib/ardm/support/ordered_set.rb +380 -0
- data/lib/ardm/support/subject.rb +33 -0
- data/lib/ardm/support/subject_set.rb +250 -0
- data/lib/ardm/version.rb +3 -0
- data/lib/ardm.rb +56 -0
- data/spec/fixtures/api_user.rb +11 -0
- data/spec/fixtures/article.rb +22 -0
- data/spec/fixtures/bookmark.rb +14 -0
- data/spec/fixtures/invention.rb +5 -0
- data/spec/fixtures/network_node.rb +23 -0
- data/spec/fixtures/person.rb +17 -0
- data/spec/fixtures/software_package.rb +22 -0
- data/spec/fixtures/ticket.rb +12 -0
- data/spec/fixtures/tshirt.rb +15 -0
- data/spec/integration/api_key_spec.rb +25 -0
- data/spec/integration/bcrypt_hash_spec.rb +45 -0
- data/spec/integration/comma_separated_list_spec.rb +85 -0
- data/spec/integration/dirty_minder_spec.rb +197 -0
- data/spec/integration/enum_spec.rb +79 -0
- data/spec/integration/epoch_time_spec.rb +59 -0
- data/spec/integration/file_path_spec.rb +158 -0
- data/spec/integration/flag_spec.rb +72 -0
- data/spec/integration/ip_address_spec.rb +151 -0
- data/spec/integration/json_spec.rb +70 -0
- data/spec/integration/slug_spec.rb +65 -0
- data/spec/integration/uri_spec.rb +136 -0
- data/spec/integration/uuid_spec.rb +102 -0
- data/spec/integration/yaml_spec.rb +85 -0
- data/spec/public/property/binary_spec.rb +41 -0
- data/spec/public/property/boolean_spec.rb +30 -0
- data/spec/public/property/class_spec.rb +28 -0
- data/spec/public/property/date_spec.rb +22 -0
- data/spec/public/property/date_time_spec.rb +22 -0
- data/spec/public/property/decimal_spec.rb +23 -0
- data/spec/public/property/discriminator_spec.rb +133 -0
- data/spec/public/property/float_spec.rb +22 -0
- data/spec/public/property/integer_spec.rb +22 -0
- data/spec/public/property/object_spec.rb +103 -0
- data/spec/public/property/serial_spec.rb +22 -0
- data/spec/public/property/string_spec.rb +22 -0
- data/spec/public/property/text_spec.rb +23 -0
- data/spec/public/property/time_spec.rb +22 -0
- data/spec/public/property_spec.rb +316 -0
- data/spec/rcov.opts +6 -0
- data/spec/schema.rb +86 -0
- data/spec/semipublic/property/binary_spec.rb +14 -0
- data/spec/semipublic/property/boolean_spec.rb +48 -0
- data/spec/semipublic/property/class_spec.rb +36 -0
- data/spec/semipublic/property/date_spec.rb +44 -0
- data/spec/semipublic/property/date_time_spec.rb +47 -0
- data/spec/semipublic/property/decimal_spec.rb +83 -0
- data/spec/semipublic/property/discriminator_spec.rb +22 -0
- data/spec/semipublic/property/float_spec.rb +83 -0
- data/spec/semipublic/property/integer_spec.rb +83 -0
- data/spec/semipublic/property/lookup_spec.rb +27 -0
- data/spec/semipublic/property/serial_spec.rb +14 -0
- data/spec/semipublic/property/string_spec.rb +14 -0
- data/spec/semipublic/property/text_spec.rb +30 -0
- data/spec/semipublic/property/time_spec.rb +49 -0
- data/spec/semipublic/property_spec.rb +51 -0
- data/spec/shared/flags_shared_spec.rb +36 -0
- data/spec/shared/identity_function_group.rb +5 -0
- data/spec/shared/public_property_spec.rb +229 -0
- data/spec/shared/semipublic_property_spec.rb +159 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +58 -0
- data/spec/unit/bcrypt_hash_spec.rb +154 -0
- data/spec/unit/csv_spec.rb +139 -0
- data/spec/unit/dirty_minder_spec.rb +64 -0
- data/spec/unit/enum_spec.rb +125 -0
- data/spec/unit/epoch_time_spec.rb +72 -0
- data/spec/unit/file_path_spec.rb +75 -0
- data/spec/unit/flag_spec.rb +114 -0
- data/spec/unit/ip_address_spec.rb +109 -0
- data/spec/unit/json_spec.rb +127 -0
- data/spec/unit/paranoid_boolean_spec.rb +142 -0
- data/spec/unit/paranoid_datetime_spec.rb +149 -0
- data/spec/unit/regexp_spec.rb +62 -0
- data/spec/unit/uri_spec.rb +64 -0
- data/spec/unit/yaml_spec.rb +111 -0
- data/tasks/spec.rake +40 -0
- data/tasks/yard.rake +9 -0
- data/tasks/yardstick.rake +19 -0
- metadata +350 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ardm::Property::Discriminator do
|
|
4
|
+
before do
|
|
5
|
+
Object.send(:remove_const, :Foo) if defined?(Foo)
|
|
6
|
+
Object.send(:remove_const, :Bar) if defined?(Bar)
|
|
7
|
+
|
|
8
|
+
class ::Foo; end
|
|
9
|
+
class ::Bar; end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
let(:name) { :type }
|
|
13
|
+
let(:type) { described_class }
|
|
14
|
+
let(:options) { {} }
|
|
15
|
+
let(:value) { Foo }
|
|
16
|
+
let(:other_value) { Bar }
|
|
17
|
+
let(:invalid_value) { 1 }
|
|
18
|
+
let(:model) { Blog::Article }
|
|
19
|
+
let(:property) { type.new(model, name, options) }
|
|
20
|
+
|
|
21
|
+
it_should_behave_like 'A semipublic Property'
|
|
22
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ardm::Property::Float do
|
|
4
|
+
let(:name) { :rating }
|
|
5
|
+
let(:type) { described_class }
|
|
6
|
+
let(:options) { {} }
|
|
7
|
+
let(:value) { 0.1 }
|
|
8
|
+
let(:other_value) { 0.2 }
|
|
9
|
+
let(:invalid_value) { '1' }
|
|
10
|
+
let(:model) { Blog::Article }
|
|
11
|
+
let(:property) { type.new(model, name, options) }
|
|
12
|
+
|
|
13
|
+
it_should_behave_like 'A semipublic Property'
|
|
14
|
+
|
|
15
|
+
describe '#typecast' do
|
|
16
|
+
it 'returns same value if a float' do
|
|
17
|
+
value = 24.0
|
|
18
|
+
property.typecast(value).should equal(value)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'returns float representation of a zero string integer' do
|
|
22
|
+
property.typecast('0').should eql(0.0)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'returns float representation of a positive string integer' do
|
|
26
|
+
property.typecast('24').should eql(24.0)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'returns float representation of a negative string integer' do
|
|
30
|
+
property.typecast('-24').should eql(-24.0)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'returns float representation of a zero string float' do
|
|
34
|
+
property.typecast('0.0').should eql(0.0)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'returns float representation of a positive string float' do
|
|
38
|
+
property.typecast('24.35').should eql(24.35)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'returns float representation of a negative string float' do
|
|
42
|
+
property.typecast('-24.35').should eql(-24.35)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'returns float representation of a zero string float, with no leading digits' do
|
|
46
|
+
property.typecast('.0').should eql(0.0)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'returns float representation of a positive string float, with no leading digits' do
|
|
50
|
+
property.typecast('.41').should eql(0.41)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'returns float representation of a zero integer' do
|
|
54
|
+
property.typecast(0).should eql(0.0)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'returns float representation of a positive integer' do
|
|
58
|
+
property.typecast(24).should eql(24.0)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'returns float representation of a negative integer' do
|
|
62
|
+
property.typecast(-24).should eql(-24.0)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'returns float representation of a zero decimal' do
|
|
66
|
+
property.typecast(BigDecimal('0.0')).should eql(0.0)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'returns float representation of a positive decimal' do
|
|
70
|
+
property.typecast(BigDecimal('24.35')).should eql(24.35)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'returns float representation of a negative decimal' do
|
|
74
|
+
property.typecast(BigDecimal('-24.35')).should eql(-24.35)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
[ Object.new, true, '0.', '-.0', 'string' ].each do |value|
|
|
78
|
+
it "does not typecast non-numeric value #{value.inspect}" do
|
|
79
|
+
property.typecast(value).should equal(value)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ardm::Property::Integer do
|
|
4
|
+
let(:name) { :age }
|
|
5
|
+
let(:type) { described_class }
|
|
6
|
+
let(:options) { {} }
|
|
7
|
+
let(:value) { 1 }
|
|
8
|
+
let(:other_value) { 2 }
|
|
9
|
+
let(:invalid_value) { '1' }
|
|
10
|
+
let(:model) { Blog::Article }
|
|
11
|
+
let(:property) { type.new(model, name, options) }
|
|
12
|
+
|
|
13
|
+
it_should_behave_like 'A semipublic Property'
|
|
14
|
+
|
|
15
|
+
describe '#typecast' do
|
|
16
|
+
it 'returns same value if an integer' do
|
|
17
|
+
value = 24
|
|
18
|
+
property.typecast(value).should equal(value)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'returns integer representation of a zero string integer' do
|
|
22
|
+
property.typecast('0').should eql(0)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it 'returns integer representation of a positive string integer' do
|
|
26
|
+
property.typecast('24').should eql(24)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it 'returns integer representation of a negative string integer' do
|
|
30
|
+
property.typecast('-24').should eql(-24)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it 'returns integer representation of a zero string float' do
|
|
34
|
+
property.typecast('0.0').should eql(0)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it 'returns integer representation of a positive string float' do
|
|
38
|
+
property.typecast('24.35').should eql(24)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'returns integer representation of a negative string float' do
|
|
42
|
+
property.typecast('-24.35').should eql(-24)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'returns integer representation of a zero string float, with no leading digits' do
|
|
46
|
+
property.typecast('.0').should eql(0)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it 'returns integer representation of a positive string float, with no leading digits' do
|
|
50
|
+
property.typecast('.41').should eql(0)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it 'returns integer representation of a zero float' do
|
|
54
|
+
property.typecast(0.0).should eql(0)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'returns integer representation of a positive float' do
|
|
58
|
+
property.typecast(24.35).should eql(24)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
it 'returns integer representation of a negative float' do
|
|
62
|
+
property.typecast(-24.35).should eql(-24)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it 'returns integer representation of a zero decimal' do
|
|
66
|
+
property.typecast(BigDecimal('0.0')).should eql(0)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it 'returns integer representation of a positive decimal' do
|
|
70
|
+
property.typecast(BigDecimal('24.35')).should eql(24)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it 'returns integer representation of a negative decimal' do
|
|
74
|
+
property.typecast(BigDecimal('-24.35')).should eql(-24)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
[ Object.new, true, '0.', '-.0', 'string' ].each do |value|
|
|
78
|
+
it "does not typecast non-numeric value #{value.inspect}" do
|
|
79
|
+
property.typecast(value).should equal(value)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module LookupFoo
|
|
4
|
+
class OtherProperty < Ardm::Property::String; end
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
describe Ardm::Property::Lookup do
|
|
8
|
+
before do
|
|
9
|
+
@klass = Class.new(Ardm::Record) do
|
|
10
|
+
self.table_name = "articles"
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
it 'should provide access to Property classes' do
|
|
15
|
+
@klass::Serial.should == Ardm::Property::Serial
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it 'should provide access to Property classes from outside of the Property namespace' do
|
|
19
|
+
@klass::OtherProperty.should eq(LookupFoo::OtherProperty)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it 'should not provide access to unknown Property classes' do
|
|
23
|
+
lambda {
|
|
24
|
+
@klass::Bla
|
|
25
|
+
}.should raise_error(NameError)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ardm::Property::Serial do
|
|
4
|
+
let(:name) { :id }
|
|
5
|
+
let(:type) { described_class }
|
|
6
|
+
let(:options) { {} }
|
|
7
|
+
let(:value) { 1 }
|
|
8
|
+
let(:other_value) { 2 }
|
|
9
|
+
let(:invalid_value) { 'foo' }
|
|
10
|
+
let(:model) { Blog::Article }
|
|
11
|
+
let(:property) { type.new(model, name, options) }
|
|
12
|
+
|
|
13
|
+
it_should_behave_like 'A semipublic Property'
|
|
14
|
+
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ardm::Property::String do
|
|
4
|
+
let(:name) { :name }
|
|
5
|
+
let(:type) { described_class }
|
|
6
|
+
let(:options) { {} }
|
|
7
|
+
let(:value) { 'value' }
|
|
8
|
+
let(:other_value) { 'return value' }
|
|
9
|
+
let(:invalid_value) { 1 }
|
|
10
|
+
let(:model) { Blog::Article }
|
|
11
|
+
let(:property) { type.new(model, name, options) }
|
|
12
|
+
|
|
13
|
+
it_should_behave_like 'A semipublic Property'
|
|
14
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ardm::Property::Text do
|
|
4
|
+
let(:name) { :title }
|
|
5
|
+
let(:type) { described_class }
|
|
6
|
+
let(:options) { {} }
|
|
7
|
+
let(:value) { 'value' }
|
|
8
|
+
let(:other_value) { 'return value' }
|
|
9
|
+
let(:invalid_value) { 1 }
|
|
10
|
+
let(:model) { Blog::Article }
|
|
11
|
+
let(:property) { type.new(model, name, options) }
|
|
12
|
+
|
|
13
|
+
it_should_behave_like 'A semipublic Property'
|
|
14
|
+
|
|
15
|
+
describe '#load' do
|
|
16
|
+
before do
|
|
17
|
+
@value = 'value'
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
subject { property.load(@value) }
|
|
21
|
+
|
|
22
|
+
let(:property) { type.new(model, name) }
|
|
23
|
+
|
|
24
|
+
it 'should delegate to #type.load' do
|
|
25
|
+
return_value = 'return value'
|
|
26
|
+
property.should_receive(:load).with(@value).and_return(return_value)
|
|
27
|
+
subject.should == return_value
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Ardm::Property::Time do
|
|
4
|
+
let(:name) { :deleted_at }
|
|
5
|
+
let(:type) { described_class }
|
|
6
|
+
let(:options) { {} }
|
|
7
|
+
let(:value) { Time.now }
|
|
8
|
+
let(:other_value) { Time.now + 15 }
|
|
9
|
+
let(:invalid_value) { 1 }
|
|
10
|
+
let(:model) { Blog::Article }
|
|
11
|
+
let(:property) { type.new(model, name, options) }
|
|
12
|
+
|
|
13
|
+
it_should_behave_like 'A semipublic Property'
|
|
14
|
+
|
|
15
|
+
describe '#typecast' do
|
|
16
|
+
describe 'and value given as a hash with keys like :year, :month, etc' do
|
|
17
|
+
it 'builds a Time instance from hash values' do
|
|
18
|
+
result = property.typecast(
|
|
19
|
+
:year => '2006',
|
|
20
|
+
:month => '11',
|
|
21
|
+
:day => '23',
|
|
22
|
+
:hour => '12',
|
|
23
|
+
:min => '0',
|
|
24
|
+
:sec => '0'
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
result.should be_kind_of(Time)
|
|
28
|
+
result.year.should eql(2006)
|
|
29
|
+
result.month.should eql(11)
|
|
30
|
+
result.day.should eql(23)
|
|
31
|
+
result.hour.should eql(12)
|
|
32
|
+
result.min.should eql(0)
|
|
33
|
+
result.sec.should eql(0)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe 'and value is a string' do
|
|
38
|
+
it 'parses the string' do
|
|
39
|
+
result = property.typecast('22:24')
|
|
40
|
+
result.hour.should eql(22)
|
|
41
|
+
result.min.should eql(24)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
it 'does not typecast non-time values' do
|
|
46
|
+
property.typecast('not-time').should eql('not-time')
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
|
|
3
|
+
# instance methods
|
|
4
|
+
describe Ardm::Property do
|
|
5
|
+
describe ".find_class" do
|
|
6
|
+
[ :Serial, :Text ].each do |type|
|
|
7
|
+
describe "with #{type}" do
|
|
8
|
+
subject { Ardm::Property.find_class(type) }
|
|
9
|
+
|
|
10
|
+
it { subject.should be(Ardm::Property.const_get(type)) }
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe ".determine_class" do
|
|
16
|
+
[ Integer, String, Float, Class, String, Time, DateTime, Date ].each do |type|
|
|
17
|
+
describe "with #{type}" do
|
|
18
|
+
subject { Ardm::Property.determine_class(type) }
|
|
19
|
+
|
|
20
|
+
it { subject.should be(Ardm::Property.const_get(type.name)) }
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe "with property subclasses" do
|
|
25
|
+
before do
|
|
26
|
+
Object.send(:remove_const, :CustomProps) if Object.const_defined?(:CustomProps)
|
|
27
|
+
|
|
28
|
+
module ::CustomProps
|
|
29
|
+
module Property
|
|
30
|
+
class Hash < Ardm::Property::Object; end
|
|
31
|
+
class Other < Ardm::Property::Object; end
|
|
32
|
+
class Serial < Ardm::Property::Object; end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "with ::Foo::Property::Hash" do
|
|
38
|
+
subject { Ardm::Property.determine_class(Hash) }
|
|
39
|
+
|
|
40
|
+
it { subject.should be(::CustomProps::Property::Hash) }
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "with ::Foo::Property::Other" do
|
|
44
|
+
subject { Ardm::Property.determine_class(::CustomProps::Property::Other) }
|
|
45
|
+
|
|
46
|
+
it { subject.should be(::CustomProps::Property::Other) }
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
share_examples_for "A property with flags" do
|
|
2
|
+
before do
|
|
3
|
+
%w[ @property_klass ].each do |ivar|
|
|
4
|
+
raise "+#{ivar}+ should be defined in before block" unless instance_variable_defined?(ivar)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
@flags = [ :one, :two, :three ]
|
|
8
|
+
|
|
9
|
+
class ::User < Ardm::Record
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
@property = User.property :item, @property_klass[@flags], :key => true
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe ".generated_classes" do
|
|
16
|
+
it "should cache the generated class" do
|
|
17
|
+
@property_klass.generated_classes[@flags].should_not be_nil
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should include :flags in accepted_options" do
|
|
22
|
+
@property_klass.accepted_options.should include(:flags)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should respond to :generated_classes" do
|
|
26
|
+
@property_klass.should respond_to(:generated_classes)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should respond to :flag_map" do
|
|
30
|
+
@property.should respond_to(:flag_map)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should be custom" do
|
|
34
|
+
@property.custom?.should be(true)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
share_examples_for 'A public Property' do
|
|
2
|
+
before do
|
|
3
|
+
%w[ @type @load_as @name @value @other_value ].each do |ivar|
|
|
4
|
+
raise "+#{ivar}+ should be defined in before block" unless instance_variable_defined?(ivar)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
module ::Blog
|
|
8
|
+
class Article < Ardm::Record
|
|
9
|
+
self.table_name = "articles"
|
|
10
|
+
property :id, Serial
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
@model = Blog::Article
|
|
15
|
+
@options ||= {}
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
describe "with a sub-type" do
|
|
19
|
+
before do
|
|
20
|
+
class ::SubType < @type; end
|
|
21
|
+
@subtype = ::SubType
|
|
22
|
+
@type.accept_options :foo, :bar
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
before do
|
|
26
|
+
@original = @type.accepted_options.dup
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
after do
|
|
30
|
+
@type.accepted_options.replace(@original - [ :foo, :bar ])
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe "predefined options" do
|
|
34
|
+
before do
|
|
35
|
+
class ::ChildSubType < @subtype
|
|
36
|
+
default nil
|
|
37
|
+
end
|
|
38
|
+
@child_subtype = ChildSubType
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "when parent type overrides a default" do
|
|
42
|
+
before do
|
|
43
|
+
@subtype.default "foo"
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
after do
|
|
47
|
+
Ardm::Property.descendants.delete(ChildSubType)
|
|
48
|
+
Object.send(:remove_const, :ChildSubType)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "should not override the child's type setting" do
|
|
52
|
+
@child_subtype.default.should eql(nil)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
after do
|
|
58
|
+
Ardm::Property.descendants.delete(SubType)
|
|
59
|
+
Object.send(:remove_const, :SubType)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe ".accept_options" do
|
|
63
|
+
describe "when provided :foo, :bar" do
|
|
64
|
+
it "should add new options" do
|
|
65
|
+
[@type, @subtype].each do |type|
|
|
66
|
+
type.accepted_options.include?(:foo).should be(true)
|
|
67
|
+
type.accepted_options.include?(:bar).should be(true)
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
it "should create predefined option setters" do
|
|
72
|
+
[@type, @subtype].each do |type|
|
|
73
|
+
type.should respond_to(:foo)
|
|
74
|
+
type.should respond_to(:bar)
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
describe "auto-generated option setters" do
|
|
79
|
+
before do
|
|
80
|
+
@type.foo true
|
|
81
|
+
@type.bar 1
|
|
82
|
+
@property = @type.new(@model, @name, @options)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should set the pre-defined option values" do
|
|
86
|
+
@property.options[:foo].should == true
|
|
87
|
+
@property.options[:bar].should == 1
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
it "should ask the superclass for the value if unknown" do
|
|
91
|
+
@subtype.foo.should == true
|
|
92
|
+
@subtype.bar.should == 1
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe ".descendants" do
|
|
99
|
+
it "should include the sub-type" do
|
|
100
|
+
@type.descendants.include?(SubType).should be(true)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe ".load_as" do
|
|
105
|
+
it "should return the load_as" do
|
|
106
|
+
[@type, @subtype].each do |type|
|
|
107
|
+
type.load_as.should be(@load_as)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "should change the load_as class" do
|
|
112
|
+
@subtype.load_as Object
|
|
113
|
+
@subtype.load_as.should be(Object)
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
[:allow_blank, :allow_nil].each do |opt|
|
|
119
|
+
describe "##{method = "#{opt}?"}" do
|
|
120
|
+
[true, false].each do |value|
|
|
121
|
+
describe "when created with :#{opt} => #{value}" do
|
|
122
|
+
before do
|
|
123
|
+
@property = @type.new(@model, @name, @options.merge(opt => value))
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
it "should return #{value}" do
|
|
127
|
+
@property.send(method).should be(value)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
describe "when created with :#{opt} => true and :required => true" do
|
|
133
|
+
it "should fail with ArgumentError" do
|
|
134
|
+
lambda {
|
|
135
|
+
@property = @type.new(@model, @name, @options.merge(opt => true, :required => true))
|
|
136
|
+
}.should raise_error(ArgumentError,
|
|
137
|
+
"options[:required] cannot be mixed with :allow_nil or :allow_blank")
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
[:key?, :required?, :index, :unique_index, :unique?].each do |method|
|
|
144
|
+
describe "##{method}" do
|
|
145
|
+
[true, false].each do |value|
|
|
146
|
+
describe "when created with :#{method} => #{value}" do
|
|
147
|
+
before do
|
|
148
|
+
opt = method.to_s.chomp('?').to_sym
|
|
149
|
+
@property = @type.new(@model, @name, @options.merge(opt => value))
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "should return #{value}" do
|
|
153
|
+
@property.send(method).should be(value)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
describe "#lazy?" do
|
|
161
|
+
describe "when created with :lazy => true, :key => false" do
|
|
162
|
+
before do
|
|
163
|
+
@property = @type.new(@model, @name, @options.merge(:lazy => true, :key => false))
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it "should return true" do
|
|
167
|
+
@property.lazy?.should be(true)
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
describe "when created with :lazy => true, :key => true" do
|
|
172
|
+
before do
|
|
173
|
+
@property = @type.new(@model, @name, @options.merge(:lazy => true, :key => true))
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it "should return false" do
|
|
177
|
+
@property.lazy?.should be(false)
|
|
178
|
+
end
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
describe '#instance_of?' do
|
|
183
|
+
subject { property.instance_of?(klass) }
|
|
184
|
+
|
|
185
|
+
let(:property) { @type.new(@model, @name, @options) }
|
|
186
|
+
|
|
187
|
+
context 'when provided the property class' do
|
|
188
|
+
let(:klass) { @type }
|
|
189
|
+
|
|
190
|
+
it { should be(true) }
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
context 'when provided the property superclass' do
|
|
194
|
+
let(:klass) { @type.superclass }
|
|
195
|
+
|
|
196
|
+
it { should be(false) }
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
context 'when provided the Ardm::Property class' do
|
|
200
|
+
let(:klass) { Ardm::Property }
|
|
201
|
+
|
|
202
|
+
it { should be(false) }
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
describe '#kind_of?' do
|
|
207
|
+
subject { property.kind_of?(klass) }
|
|
208
|
+
|
|
209
|
+
let(:property) { @type.new(@model, @name, @options) }
|
|
210
|
+
|
|
211
|
+
context 'when provided the property class' do
|
|
212
|
+
let(:klass) { @type }
|
|
213
|
+
|
|
214
|
+
it { should be(true) }
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
context 'when provided the property superclass' do
|
|
218
|
+
let(:klass) { @type.superclass }
|
|
219
|
+
|
|
220
|
+
it { should be(true) }
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
context 'when provided the Ardm::Property class' do
|
|
224
|
+
let(:klass) { Ardm::Property }
|
|
225
|
+
|
|
226
|
+
it { should be(true) }
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
end
|