hashme 0.2.5 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +1 -1
- data/.travis.yml +24 -0
- data/Gemfile.activemodel-4.x +4 -0
- data/Gemfile.activemodel-5.x +4 -0
- data/README.md +19 -5
- data/Rakefile +6 -0
- data/hashme.gemspec +2 -2
- data/lib/hashme/attributes.rb +1 -1
- data/lib/hashme/casted_array.rb +61 -38
- data/lib/hashme/properties.rb +4 -4
- data/lib/hashme/property.rb +9 -4
- data/lib/hashme/property_casting.rb +13 -3
- data/lib/hashme/validations/casted_attribute_validator.rb +1 -1
- data/lib/hashme/version.rb +1 -1
- data/lib/hashme.rb +2 -0
- data/spec/hashme/base_spec.rb +2 -2
- data/spec/hashme/casted_array_spec.rb +105 -29
- data/spec/hashme/properties_spec.rb +9 -3
- data/spec/hashme/property_casting_spec.rb +42 -5
- data/spec/hashme/property_spec.rb +8 -7
- metadata +12 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 157002395c66c0c5a0d4ffe7c13cf16f93a5ee016a8c42c9388362b7f80b65ae
|
4
|
+
data.tar.gz: '032850cb9db195516320a53afc10432d918b0f066fc4d0ed0cf7291216a336f5'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1c6820691be9c3b71e0e570d3bb4a37315e896e3203096017905750f9c18aa122039bc7a889dc67a1ff24ae2af7da2956803de806490e7224e3b40bda2de0f6c
|
7
|
+
data.tar.gz: 8e397827a0eb98c019e88b2a4d6155817693d50be1e90c33f6ff8a295dbd980198c24887daae41d68a3965fa50e96a987fa125e379c7503b8d0878c86da3b1fd
|
data/.gitignore
CHANGED
data/.travis.yml
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
language: ruby
|
2
|
+
gemfile:
|
3
|
+
- Gemfile.activemodel-4.x
|
4
|
+
- Gemfile.activemodel-5.x
|
5
|
+
rvm:
|
6
|
+
- 2.0.0
|
7
|
+
- 2.1.10
|
8
|
+
- 2.2.4
|
9
|
+
- 2.3.0
|
10
|
+
- jruby
|
11
|
+
- rbx
|
12
|
+
before_install:
|
13
|
+
- gem install bundler
|
14
|
+
env:
|
15
|
+
- JRUBY_OPTS=--2.0
|
16
|
+
matrix:
|
17
|
+
allow_failures:
|
18
|
+
- rvm: rbx # Sorry, don't have time for these failures!
|
19
|
+
- rvm: 2.0.0
|
20
|
+
gemfile: Gemfile.activemodel-5.x
|
21
|
+
- rvm: 2.1.10
|
22
|
+
gemfile: Gemfile.activemodel-5.x
|
23
|
+
- rvm: jruby
|
24
|
+
gemfile: Gemfile.activemodel-5.x
|
data/README.md
CHANGED
@@ -1,12 +1,14 @@
|
|
1
1
|
# Hashme
|
2
2
|
|
3
|
+
[![Build Status](https://travis-ci.org/samlown/hashme.png)](https://travis-ci.org/samlown/hashme)
|
4
|
+
|
3
5
|
Hashes are great, but sometimes you need a bit more structure.
|
4
6
|
|
5
7
|
Hashme helps you create simple models that allow you to initialize and
|
6
8
|
generate hashes that you can serialize and store as you wish.
|
7
9
|
|
8
10
|
Its a bit like ActiveRecord, but without all the messy database stuff,
|
9
|
-
and of course you can nest to you're heart's content.
|
11
|
+
and of course you can nest models to you're heart's content.
|
10
12
|
|
11
13
|
A few situations where you might find Hashme useful:
|
12
14
|
|
@@ -69,13 +71,13 @@ class Kennel
|
|
69
71
|
end
|
70
72
|
|
71
73
|
# Build a kennel
|
72
|
-
kennel = Kennel.new(:name => "Goaway Kitty Home", :location => Point.new(40.333,-3.4555))
|
74
|
+
kennel = Kennel.new(:name => "Goaway Kitty Home", :location => Point.new(40.333,-3.4555), :cats => [])
|
73
75
|
|
74
76
|
# Add a kitten using an object
|
75
|
-
kennel << kitty
|
77
|
+
kennel.cats << kitty
|
76
78
|
|
77
79
|
# Add a new cat using a raw hash
|
78
|
-
kennel << {
|
80
|
+
kennel.cats << {
|
79
81
|
:name => "Felix",
|
80
82
|
:description => "Black and white"
|
81
83
|
}
|
@@ -118,6 +120,18 @@ u.errors.first # [:email, "can't be blank"]
|
|
118
120
|
|
119
121
|
## History
|
120
122
|
|
123
|
+
### 0.3.0 - 2023-01-23
|
124
|
+
|
125
|
+
* Making `CastArray` provide the whole `Array` API by inherityin from it
|
126
|
+
* Removing default value fallback to fix bug with booleans
|
127
|
+
* Adding support for `URI` objects typecasting
|
128
|
+
* Adding `Boolean` as an alias of `TrueClass`
|
129
|
+
|
130
|
+
### 0.2.6 - 2017-09-12
|
131
|
+
|
132
|
+
* Setting ActiveModel minimum to 4.0, adding travis config to test both 4.0 and 5.0. (@samlown)
|
133
|
+
* Adding support for using `Proc` type as default values for properties (@apoloval)
|
134
|
+
|
121
135
|
### 0.2.5 - 2016-06-03 - Again!
|
122
136
|
|
123
137
|
* Adding support for deleting attributes by setting them to nil to keep output clean.
|
@@ -151,7 +165,7 @@ u.errors.first # [:email, "can't be blank"]
|
|
151
165
|
* Refactoring to use `class_attribute` for properties hash for improved inheritance.
|
152
166
|
|
153
167
|
### 0.1.1 - 2014-01-21
|
154
|
-
|
168
|
+
|
155
169
|
* Fixing dependency on ActiveModel >= 3.0
|
156
170
|
|
157
171
|
### 0.1.0 - 2014-01-15
|
data/Rakefile
CHANGED
data/hashme.gemspec
CHANGED
@@ -18,9 +18,9 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
-
spec.add_dependency "activemodel", ">=
|
21
|
+
spec.add_dependency "activemodel", ">= 4.0"
|
22
22
|
|
23
|
-
spec.add_development_dependency "bundler"
|
23
|
+
spec.add_development_dependency "bundler"
|
24
24
|
spec.add_development_dependency "rake"
|
25
25
|
spec.add_development_dependency "rspec"
|
26
26
|
end
|
data/lib/hashme/attributes.rb
CHANGED
data/lib/hashme/casted_array.rb
CHANGED
@@ -2,60 +2,83 @@ require 'forwardable'
|
|
2
2
|
|
3
3
|
module Hashme
|
4
4
|
|
5
|
-
# The Hashme CastedArray is a special
|
6
|
-
|
7
|
-
#
|
8
|
-
# Adding objects will automatically assign the Array's owner, as opposed
|
9
|
-
# to the array itself.
|
10
|
-
#
|
11
|
-
class CastedArray
|
12
|
-
extend Forwardable
|
13
|
-
|
5
|
+
# The Hashme CastedArray is a special Array that typecasts each item according to a given property
|
6
|
+
class CastedArray < Array
|
14
7
|
attr_reader :property
|
15
8
|
|
16
|
-
|
17
|
-
:to_a, :==, :eql?, :size,
|
18
|
-
:first, :last, :at, :length,
|
19
|
-
:each, :reject, :empty?, :map, :collect,
|
20
|
-
:clear, :pop, :shift, :delete, :delete_at,
|
21
|
-
:encode_json, :as_json, :to_json,
|
22
|
-
:inspect, :any?
|
23
|
-
|
24
|
-
def initialize(property, owner, values = [])
|
25
|
-
@_array = []
|
9
|
+
def initialize(property, vals = [])
|
26
10
|
@property = property
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
11
|
+
super build_all(vals)
|
12
|
+
end
|
13
|
+
|
14
|
+
def <<(val)
|
15
|
+
super build(val)
|
16
|
+
end
|
17
|
+
|
18
|
+
def push(*vals)
|
19
|
+
super *build_all(vals)
|
20
|
+
end
|
21
|
+
|
22
|
+
alias append push
|
23
|
+
|
24
|
+
def concat(*arrays)
|
25
|
+
super *arrays.map { |array| build_all(array) }
|
32
26
|
end
|
33
27
|
|
34
|
-
def
|
35
|
-
|
28
|
+
def insert(index, *vals)
|
29
|
+
super index, *build_all(vals)
|
36
30
|
end
|
37
31
|
|
38
|
-
def
|
39
|
-
|
32
|
+
def unshift(*vals)
|
33
|
+
super *build_all(vals)
|
40
34
|
end
|
41
35
|
|
42
|
-
|
43
|
-
|
36
|
+
alias prepend unshift
|
37
|
+
|
38
|
+
def replace(array)
|
39
|
+
super build_all(array)
|
44
40
|
end
|
45
|
-
|
46
|
-
def []
|
47
|
-
|
41
|
+
|
42
|
+
def []=(*args)
|
43
|
+
args = args.dup
|
44
|
+
args[-1] = build(args[-1])
|
45
|
+
super *args
|
48
46
|
end
|
49
47
|
|
50
|
-
def
|
51
|
-
|
48
|
+
def fill(*args, &block)
|
49
|
+
if block
|
50
|
+
super *args do |index|
|
51
|
+
val = block.call(index)
|
52
|
+
build(val)
|
53
|
+
end
|
54
|
+
else
|
55
|
+
args = args.dup
|
56
|
+
args[0] = build(args[0])
|
57
|
+
super *args
|
58
|
+
end
|
52
59
|
end
|
53
|
-
|
60
|
+
|
61
|
+
def collect!(&block)
|
62
|
+
if block
|
63
|
+
super do |element|
|
64
|
+
val = block.call(element)
|
65
|
+
build(val)
|
66
|
+
end
|
67
|
+
else
|
68
|
+
super
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
alias map! collect!
|
73
|
+
|
54
74
|
protected
|
55
75
|
|
56
|
-
def
|
57
|
-
|
76
|
+
def build_all(vals)
|
77
|
+
vals.map { |val| build(val) }
|
58
78
|
end
|
59
79
|
|
80
|
+
def build(val)
|
81
|
+
property.build(val)
|
82
|
+
end
|
60
83
|
end
|
61
84
|
end
|
data/lib/hashme/properties.rb
CHANGED
@@ -14,7 +14,7 @@ module Hashme
|
|
14
14
|
def set_attribute(name, value)
|
15
15
|
property = get_property(name)
|
16
16
|
if property
|
17
|
-
value = property.build(
|
17
|
+
value = property.build(value)
|
18
18
|
if value.nil?
|
19
19
|
delete(property.name)
|
20
20
|
else
|
@@ -45,9 +45,9 @@ module Hashme
|
|
45
45
|
set_attribute(key, value)
|
46
46
|
end
|
47
47
|
end
|
48
|
-
|
48
|
+
|
49
49
|
private
|
50
|
-
|
50
|
+
|
51
51
|
def get_property(name)
|
52
52
|
self.class.properties[name.to_sym]
|
53
53
|
end
|
@@ -68,7 +68,7 @@ module Hashme
|
|
68
68
|
def define_property_methods(property)
|
69
69
|
# Getter
|
70
70
|
define_method(property.name) do
|
71
|
-
get_attribute(property.name)
|
71
|
+
get_attribute(property.name)
|
72
72
|
end
|
73
73
|
# Setter
|
74
74
|
define_method "#{property.name}=" do |value|
|
data/lib/hashme/property.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Hashme
|
2
2
|
class Property
|
3
3
|
|
4
|
-
attr_reader :name, :type, :
|
4
|
+
attr_reader :name, :type, :array
|
5
5
|
|
6
6
|
def initialize(name, type, opts = {})
|
7
7
|
@name = name.to_sym
|
@@ -27,12 +27,17 @@ module Hashme
|
|
27
27
|
name
|
28
28
|
end
|
29
29
|
|
30
|
+
def default
|
31
|
+
return @default.call if @default.is_a?(Proc)
|
32
|
+
@default
|
33
|
+
end
|
34
|
+
|
30
35
|
# Build a new object of the type defined by the property.
|
31
|
-
def build(
|
36
|
+
def build(value)
|
32
37
|
if array && value.is_a?(Array)
|
33
|
-
CastedArray.new(self,
|
38
|
+
CastedArray.new(self, value)
|
34
39
|
else
|
35
|
-
PropertyCasting.cast(self,
|
40
|
+
PropertyCasting.cast(self, value)
|
36
41
|
end
|
37
42
|
end
|
38
43
|
|
@@ -1,5 +1,8 @@
|
|
1
1
|
module Hashme
|
2
2
|
|
3
|
+
# Alias TrueClass as Boolean, so that it can be used as property types
|
4
|
+
Boolean = TrueClass
|
5
|
+
|
3
6
|
# Special property casting for reveiving data from sources without Ruby types, such as query
|
4
7
|
# parameters from an API or JSON documents.
|
5
8
|
#
|
@@ -7,10 +10,10 @@ module Hashme
|
|
7
10
|
module PropertyCasting
|
8
11
|
extend self
|
9
12
|
|
10
|
-
CASTABLE_TYPES = [String, Symbol, TrueClass, Integer, Float, BigDecimal, DateTime, Time, Date, Class]
|
13
|
+
CASTABLE_TYPES = [String, Symbol, TrueClass, Integer, Float, BigDecimal, DateTime, Time, Date, Class, URI]
|
11
14
|
|
12
15
|
# Automatically typecast the provided value into an instance of the provided type.
|
13
|
-
def cast(property,
|
16
|
+
def cast(property, value)
|
14
17
|
return nil if value.nil?
|
15
18
|
type = property.type
|
16
19
|
if value.instance_of?(type) || type == Object
|
@@ -103,7 +106,7 @@ module Hashme
|
|
103
106
|
typecast_hash_to_date(value)
|
104
107
|
elsif value.is_a?(Time) # sometimes people think date is time!
|
105
108
|
value.to_date
|
106
|
-
elsif value.to_s =~
|
109
|
+
elsif value.to_s =~ /ˆ(\d{4})[\-|\/](\d{2})[\-|\/](\d{2})$/
|
107
110
|
# Faster than parsing the date
|
108
111
|
Date.new($1.to_i, $2.to_i, $3.to_i)
|
109
112
|
else
|
@@ -186,5 +189,12 @@ module Hashme
|
|
186
189
|
nil
|
187
190
|
end
|
188
191
|
|
192
|
+
# Typecast a value to URI
|
193
|
+
def typecast_to_uri(value)
|
194
|
+
URI(value)
|
195
|
+
rescue ArgumentError
|
196
|
+
nil
|
197
|
+
end
|
198
|
+
|
189
199
|
end
|
190
200
|
end
|
data/lib/hashme/version.rb
CHANGED
data/lib/hashme.rb
CHANGED
data/spec/hashme/base_spec.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Hashme do
|
4
|
-
|
4
|
+
|
5
5
|
before :each do
|
6
6
|
@model = Class.new do
|
7
7
|
include Hashme
|
8
8
|
property :name, String
|
9
9
|
end
|
10
10
|
end
|
11
|
-
|
11
|
+
|
12
12
|
describe '.build' do
|
13
13
|
it "should create a Model and give a block to build it" do
|
14
14
|
expect(@model).to receive(:call_in_block)
|
@@ -1,11 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Hashme::CastedArray do
|
4
|
-
|
5
|
-
let :owner do
|
6
|
-
double()
|
7
|
-
end
|
8
|
-
|
9
4
|
let :submodel do
|
10
5
|
Class.new do
|
11
6
|
include Hashme
|
@@ -13,43 +8,124 @@ describe Hashme::CastedArray do
|
|
13
8
|
end
|
14
9
|
end
|
15
10
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
11
|
+
let :property do
|
12
|
+
Hashme::Property.new(:item, submodel)
|
13
|
+
end
|
14
|
+
|
15
|
+
subject do
|
16
|
+
Hashme::CastedArray.new(property, [{:name => 'test'}])
|
17
|
+
end
|
23
18
|
|
19
|
+
describe "#initialize" do
|
24
20
|
it "should prepare array" do
|
25
|
-
expect(
|
21
|
+
expect(subject.length).to eql(1)
|
26
22
|
end
|
27
23
|
|
28
24
|
it "should set property" do
|
29
|
-
expect(
|
25
|
+
expect(subject.property).to eql(property)
|
30
26
|
end
|
31
27
|
|
32
28
|
it "should instantiate and cast each value" do
|
33
|
-
expect(
|
34
|
-
expect(
|
29
|
+
expect(subject.first.class).to eql(submodel)
|
30
|
+
expect(subject.first.name).to eql('test')
|
35
31
|
end
|
36
32
|
end
|
37
33
|
|
38
|
-
|
39
|
-
subject
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
Hashme::Property.new(:item, submodel)
|
44
|
-
end
|
34
|
+
it "should cast items added to the array" do
|
35
|
+
subject << {:name => 'test2'}
|
36
|
+
expect(subject.last.class).to eql(submodel)
|
37
|
+
expect(subject.last.name).to eql('test2')
|
38
|
+
end
|
45
39
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
40
|
+
it "should cast items using `push`" do
|
41
|
+
subject.push({ :name => 'test2'}, { :name => 'test3' })
|
42
|
+
expect(subject.last.class).to eql(submodel)
|
43
|
+
expect(subject.last.name).to eql('test3')
|
44
|
+
end
|
45
|
+
|
46
|
+
it "should cast items using `concat`" do
|
47
|
+
subject.concat([{ :name => 'test2'}], [{ :name => 'test3' }])
|
48
|
+
expect(subject.last.class).to eql(submodel)
|
49
|
+
expect(subject.last.name).to eql('test3')
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should cast items using `insert`" do
|
53
|
+
subject.insert(0, { :name => 'test2'}, { :name => 'test3' })
|
54
|
+
expect(subject[1].class).to eql(submodel)
|
55
|
+
expect(subject[1].name).to eql('test3')
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should cast items using `unshift`" do
|
59
|
+
subject.unshift({ :name => 'test2'}, { :name => 'test3' })
|
60
|
+
expect(subject[1].class).to eql(submodel)
|
61
|
+
expect(subject[1].name).to eql('test3')
|
62
|
+
end
|
63
|
+
|
64
|
+
it "should cast items using `replace`" do
|
65
|
+
subject.replace([{ :name => 'test2'}, { :name => 'test3' }])
|
66
|
+
expect(subject[1].class).to eql(submodel)
|
67
|
+
expect(subject[1].name).to eql('test3')
|
68
|
+
end
|
69
|
+
|
70
|
+
it "should cast items using `[]=`" do
|
71
|
+
subject[5, 10] = { :name => 'test2'}
|
72
|
+
expect(subject[5].class).to eql(submodel)
|
73
|
+
expect(subject[5].name).to eql('test2')
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should cast items using fill with block" do
|
77
|
+
subject.fill(0) { |index| { :name => "test#{index}" } }
|
78
|
+
expect(subject.last.class).to eql(submodel)
|
79
|
+
expect(subject.last.name).to eql('test0')
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should cast items using fill without block" do
|
83
|
+
subject.fill({ :name => "test-filled" }, 0)
|
84
|
+
expect(subject.last.class).to eql(submodel)
|
85
|
+
expect(subject.last.name).to eql('test-filled')
|
86
|
+
end
|
87
|
+
|
88
|
+
it "should cast items using `collect!` with a block" do
|
89
|
+
subject.collect! { |item| { :name => "Mapped #{item.name}" } }
|
90
|
+
expect(subject.first.name).to eql('Mapped test')
|
91
|
+
end
|
52
92
|
|
93
|
+
it "should support Enumerable methods" do
|
94
|
+
map = subject.map(&:name)
|
95
|
+
expect(map).to be_an(Enumerable)
|
96
|
+
expect(map.first).to eql('test')
|
53
97
|
end
|
54
98
|
|
99
|
+
it "should compare for equality with CastedArrays" do
|
100
|
+
same = Hashme::CastedArray.new(property, [{:name => 'test'}])
|
101
|
+
different = Hashme::CastedArray.new(property, [{:name => 'test2'}])
|
102
|
+
|
103
|
+
expect(subject == same).to be(true)
|
104
|
+
expect(subject.eql?(same)).to be(true)
|
105
|
+
|
106
|
+
expect(subject == different).to be(false)
|
107
|
+
expect(subject.eql?(different)).to be(false)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "should compare for equality with Arrays" do
|
111
|
+
same = [submodel.new(:name => 'test')]
|
112
|
+
different = [submodel.new(:name => 'test2')]
|
113
|
+
|
114
|
+
expect(subject == same).to be(true)
|
115
|
+
expect(subject.eql?(same)).to be(true)
|
116
|
+
|
117
|
+
expect(subject == different).to be(false)
|
118
|
+
expect(subject.eql?(different)).to be(false)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "should be compared for equality with Arrays" do
|
122
|
+
same = [submodel.new(:name => 'test')]
|
123
|
+
different = [submodel.new(:name => 'test2')]
|
124
|
+
|
125
|
+
expect(same == subject).to be(true)
|
126
|
+
expect(same.eql?(subject)).to be(true)
|
127
|
+
|
128
|
+
expect(different == same).to be(false)
|
129
|
+
expect(different.eql?(same)).to be(false)
|
130
|
+
end
|
55
131
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Hashme::Properties do
|
4
|
-
|
4
|
+
|
5
5
|
before :all do
|
6
6
|
@aux_model = Class.new do
|
7
7
|
include Hashme
|
@@ -39,7 +39,7 @@ describe Hashme::Properties do
|
|
39
39
|
it "should set and cast attribute with property" do
|
40
40
|
property = model.send(:properties)[:name]
|
41
41
|
name = "Fred Flinstone"
|
42
|
-
expect(property).to receive(:build).with(
|
42
|
+
expect(property).to receive(:build).with(name).and_return(name)
|
43
43
|
obj.set_attribute(:name, name)
|
44
44
|
expect(obj[:name]).to eql(name)
|
45
45
|
end
|
@@ -111,12 +111,18 @@ describe Hashme::Properties do
|
|
111
111
|
obj.desc = "test"
|
112
112
|
expect(obj.desc).to eql("test")
|
113
113
|
end
|
114
|
-
|
114
|
+
|
115
115
|
it "should return nil on property with no default" do
|
116
116
|
model.property :nickname, String
|
117
117
|
expect(obj.nickname).to be_nil
|
118
118
|
end
|
119
119
|
|
120
|
+
it 'should not return the default value when a Boolean is set to false' do
|
121
|
+
model.property :flag, TrueClass, :default => true
|
122
|
+
obj.flag = false
|
123
|
+
expect(obj.flag).to be(false)
|
124
|
+
end
|
125
|
+
|
120
126
|
it "should create helper method with support for default values" do
|
121
127
|
model.property :name, String, :default => "Sam"
|
122
128
|
expect(obj.name).to eql("Sam")
|
@@ -2,7 +2,7 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
class Course
|
4
4
|
include Hashme
|
5
|
-
|
5
|
+
|
6
6
|
property :title, String
|
7
7
|
property :participants, [Object]
|
8
8
|
property :ends_at, Time
|
@@ -12,10 +12,11 @@ class Course
|
|
12
12
|
property :started_on, Date
|
13
13
|
property :updated_at, DateTime
|
14
14
|
property :active, TrueClass
|
15
|
-
property :very_active,
|
15
|
+
property :very_active, Boolean
|
16
16
|
property :klass, Class
|
17
17
|
property :currency, String, :default => 'EUR'
|
18
18
|
property :symbol, Symbol
|
19
|
+
property :uri, URI
|
19
20
|
end
|
20
21
|
|
21
22
|
describe Hashme::PropertyCasting do
|
@@ -507,6 +508,18 @@ describe Hashme::PropertyCasting do
|
|
507
508
|
expect(course.started_on.day).to eql(20)
|
508
509
|
expect(course.started_on.year).to eql(2006)
|
509
510
|
end
|
511
|
+
|
512
|
+
it 'parses date with wrong formatted year (ensure consider the beginning of string)' do
|
513
|
+
course.started_on = 'abc02016-10-03'
|
514
|
+
expect(course['started_on'].month).to eql(10)
|
515
|
+
expect(course['started_on'].day).to eql(03)
|
516
|
+
expect(course['started_on'].year).to eql(2016)
|
517
|
+
end
|
518
|
+
|
519
|
+
it 'does not typecast wrongly formatted dates (ensure consider the end of string)' do
|
520
|
+
course.started_on = '2016-10-030'
|
521
|
+
expect(course['started_on']).to be_nil
|
522
|
+
end
|
510
523
|
end
|
511
524
|
|
512
525
|
it 'does not typecast non-date values' do
|
@@ -586,19 +599,19 @@ describe Hashme::PropertyCasting do
|
|
586
599
|
end
|
587
600
|
end
|
588
601
|
|
589
|
-
describe 'when type primitive is a
|
602
|
+
describe 'when type primitive is a TrueClass' do
|
590
603
|
|
591
604
|
[ true, 'true', 'TRUE', '1', 1, 't', 'T' ].each do |value|
|
592
605
|
it "returns true when value is #{value.inspect}" do
|
593
606
|
course.active = value
|
594
|
-
expect(course['active']).to
|
607
|
+
expect(course['active']).to be(true)
|
595
608
|
end
|
596
609
|
end
|
597
610
|
|
598
611
|
[ false, 'false', 'FALSE', '0', 0, 'f', 'F' ].each do |value|
|
599
612
|
it "returns false when value is #{value.inspect}" do
|
600
613
|
course.active = value
|
601
|
-
expect(course['active']).to
|
614
|
+
expect(course['active']).to be(false)
|
602
615
|
end
|
603
616
|
end
|
604
617
|
|
@@ -608,5 +621,29 @@ describe Hashme::PropertyCasting do
|
|
608
621
|
expect(course['active']).to be_nil
|
609
622
|
end
|
610
623
|
end
|
624
|
+
|
625
|
+
it "supports Boolean as an alias of TrueClass" do
|
626
|
+
course.very_active = 't'
|
627
|
+
expect(course['very_active']).to be(true)
|
628
|
+
end
|
629
|
+
|
630
|
+
end
|
631
|
+
|
632
|
+
describe 'when type primitive is an URI' do
|
633
|
+
it 'returns same value if an uri' do
|
634
|
+
value = URI('https://invopop.com')
|
635
|
+
course.uri = value
|
636
|
+
expect(course['uri']).to equal(value)
|
637
|
+
end
|
638
|
+
|
639
|
+
it 'returns an URI if parses as one' do
|
640
|
+
course.uri = 'https://invopop.com'
|
641
|
+
expect(course['uri']).to eql(URI('https://invopop.com'))
|
642
|
+
end
|
643
|
+
|
644
|
+
it 'does not typecast non-uri values' do
|
645
|
+
course.uri = 1234
|
646
|
+
expect(course['uri']).to be_nil
|
647
|
+
end
|
611
648
|
end
|
612
649
|
end
|
@@ -6,10 +6,6 @@ describe Hashme::Property do
|
|
6
6
|
described_class
|
7
7
|
end
|
8
8
|
|
9
|
-
let :owner do
|
10
|
-
double()
|
11
|
-
end
|
12
|
-
|
13
9
|
let :submodel do
|
14
10
|
Class.new do
|
15
11
|
include Hashme
|
@@ -36,6 +32,11 @@ describe Hashme::Property do
|
|
36
32
|
prop = subject.new(:name, String, :default => "Freddo")
|
37
33
|
expect(prop.default).to eql("Freddo")
|
38
34
|
end
|
35
|
+
|
36
|
+
it "should accept a default option from a Proc" do
|
37
|
+
prop = subject.new(:name, String, :default => -> { "Freddo" })
|
38
|
+
expect(prop.default).to eql("Freddo")
|
39
|
+
end
|
39
40
|
end
|
40
41
|
|
41
42
|
describe "#to_s" do
|
@@ -56,7 +57,7 @@ describe Hashme::Property do
|
|
56
57
|
context "without an array" do
|
57
58
|
it "should build a new object" do
|
58
59
|
prop = subject.new(:date, Time)
|
59
|
-
obj = prop.build(
|
60
|
+
obj = prop.build("2013-06-02T12:00:00Z")
|
60
61
|
expect(obj.class).to eql(Time)
|
61
62
|
expect(obj).to eql(Time.utc(2013, 6, 2, 12, 0, 0))
|
62
63
|
end
|
@@ -65,13 +66,13 @@ describe Hashme::Property do
|
|
65
66
|
context "with an array" do
|
66
67
|
it "should convert regular array to casted array" do
|
67
68
|
prop = subject.new(:dates, [Time])
|
68
|
-
obj = prop.build(
|
69
|
+
obj = prop.build(["2013-06-02T12:00:00"])
|
69
70
|
expect(obj.class).to eql(Hashme::CastedArray)
|
70
71
|
expect(obj.first.class).to eql(Time)
|
71
72
|
end
|
72
73
|
it "should handle complex objects" do
|
73
74
|
prop = subject.new(:items, [submodel])
|
74
|
-
obj = prop.build(
|
75
|
+
obj = prop.build([{:name => 'test'}])
|
75
76
|
expect(obj.class).to eql(Hashme::CastedArray)
|
76
77
|
expect(obj.first.class).to eql(submodel)
|
77
78
|
expect(obj.first.name).to eql('test')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hashme
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sam Lown
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2023-01-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activemodel
|
@@ -16,28 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '4.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '4.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '
|
33
|
+
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '
|
40
|
+
version: '0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: rake
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -75,7 +75,10 @@ extra_rdoc_files: []
|
|
75
75
|
files:
|
76
76
|
- ".gitignore"
|
77
77
|
- ".rspec"
|
78
|
+
- ".travis.yml"
|
78
79
|
- Gemfile
|
80
|
+
- Gemfile.activemodel-4.x
|
81
|
+
- Gemfile.activemodel-5.x
|
79
82
|
- LICENSE.txt
|
80
83
|
- README.md
|
81
84
|
- Rakefile
|
@@ -116,8 +119,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
116
119
|
- !ruby/object:Gem::Version
|
117
120
|
version: '0'
|
118
121
|
requirements: []
|
119
|
-
|
120
|
-
rubygems_version: 2.4.6
|
122
|
+
rubygems_version: 3.4.1
|
121
123
|
signing_key:
|
122
124
|
specification_version: 4
|
123
125
|
summary: Easily define simple models that can be easily serialized and de-serialized.
|