structure 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -3,7 +3,7 @@ Structure
3
3
 
4
4
  Structure is a better Struct.
5
5
 
6
- It does wonders when modeling ephemeral data fed in from an API.
6
+ It works great when modeling ephemeral data fed in from an API.
7
7
 
8
8
  #_ d
9
9
  ##_ d#
@@ -38,10 +38,10 @@ Require:
38
38
  Define a model:
39
39
 
40
40
  class Person < Structure
41
- key :name
42
- key :age, :type => Integer
43
- key :friends, :type => Array, :default => []
44
- key :partner, :type => Structure
41
+ key :name
42
+ key :age, :type => Integer
43
+ has_many :friends
44
+ has_one :partner
45
45
  end
46
46
 
47
47
  Conjure an object:
@@ -54,27 +54,24 @@ Typecast values:
54
54
  p1.age
55
55
  => 28
56
56
 
57
- Boast ORM-esque association idioms:
57
+ Use ORM-esque association idioms:
58
58
 
59
- p2 = Person.new :name => 'Michel'
60
- p1.friends << p2 # has many
59
+ p2 = Person.new
60
+ p1.friends << p2
61
61
 
62
- p3 = Person.new :name => 'Félix'
63
- p1.partner = p3 # has one
64
-
65
- Dump good-looking JSON:
62
+ Dump well-structured JSON:
66
63
 
67
64
  require 'structure/json'
68
65
 
69
66
  json = p1.to_json
70
- => {"json_class":"Person","name":"John","age":28,"friends":[{"json_class":"Person","name": "Jane","age":null,"friends":[]}]}
67
+ => {"json_class":"Person","name":"John","age":28,"friends":[{"json_class":"Person","name":null,"age":null,"friends":[]}],"partner":null}
71
68
 
72
- Load the JSON elsewhere back into Ruby seamlessly, provided you have the same
69
+ Load the JSON elsewhere into Ruby seamlessly, provided you have the same
73
70
  models set up:
74
71
 
75
72
  person = JSON.parse(json)
76
73
  person.friends.first
77
- => #<Person:0x0000010107d030 @attributes={:name=>"Jane", :age=>nil, :friends=>[#<Person:0x0000010107d030 ...>]}, @modifiable=true>
74
+ => #<Person:0x0000010107d030 @attributes={:name=>nil, :age=>nil, :friends=>[], :partner=>nil}, @modifiable=true>
78
75
 
79
76
  Throw in some Active Model modules...
80
77
 
@@ -84,7 +81,6 @@ Throw in some Active Model modules...
84
81
  include ActiveModel::Validations
85
82
 
86
83
  key :title
87
- key :authors, :type => Array, :default => []
88
84
 
89
85
  validates_presence_of :title
90
86
  end
@@ -11,12 +11,23 @@ class Structure
11
11
 
12
12
  TYPES = [Array, Boolean, Float, Hash, Integer, String, Structure]
13
13
 
14
+ # A shortcut to define an attribute that corresponds to an array of other
15
+ # objects, possibly Structures.
16
+ def self.has_many(name)
17
+ key name, :type => Array, :default => []
18
+ end
19
+
20
+ # A shortcut to define an attribute that corresponds to another Structure.
21
+ def self.has_one(name)
22
+ key name, :type => Structure
23
+ end
24
+
14
25
  # Defines an attribute key.
15
26
  #
16
27
  # Takes a name and an optional hash of options. Available options are:
17
28
  #
18
- # * :type, which can be Array, Boolean, Float, Integer, JSON, Pathname,
19
- # String, or URI. If not specified, type defaults to String.
29
+ # * :type, which can be Array, Boolean, Float, Hash, Integer, String, or
30
+ # Structure. If not specified, type defaults to String.
20
31
  # * :default, which sets the default value for the attribute.
21
32
  #
22
33
  # class Book
@@ -58,6 +69,9 @@ class Structure
58
69
  end
59
70
  end
60
71
  elsif [Hash, Structure].include? type
72
+
73
+ # Raise an exception rather than typecast if type is Hash or
74
+ # Structure.
61
75
  lambda do |value|
62
76
  unless value.is_a? type
63
77
  raise TypeError, "#{value} is not a #{type}"
@@ -73,7 +87,7 @@ class Structure
73
87
 
74
88
  # Define a setter.
75
89
  define_method("#{name}=") do |value|
76
- modifiable[name] = value.nil? ? nil : typecast.call(value)
90
+ @attributes[name] = value.nil? ? nil : typecast.call(value)
77
91
  end
78
92
  end
79
93
  end
@@ -123,13 +137,4 @@ class Structure
123
137
  attributes
124
138
  end
125
139
  end
126
-
127
- def modifiable
128
- begin
129
- @modifiable = true
130
- rescue
131
- raise TypeError, "can't modify frozen #{self.class}"
132
- end
133
- @attributes
134
- end
135
140
  end
@@ -1,3 +1,3 @@
1
1
  class Structure
2
- VERSION = '0.5.0'
2
+ VERSION = '0.6.0'
3
3
  end
@@ -1,5 +1,5 @@
1
1
  class Person < Structure
2
2
  key :name
3
3
  key :age, :type => Integer
4
- key :friends, :type => Array, :default => []
4
+ has_many :friends
5
5
  end
@@ -154,7 +154,7 @@ describe Structure do
154
154
 
155
155
  context "when type is Structure" do
156
156
  before(:all) do
157
- Person.key :father, :type => Structure
157
+ Person.has_one :father
158
158
  end
159
159
 
160
160
  context "when setting to a value that is not a Structure" do
@@ -179,18 +179,6 @@ describe Structure do
179
179
  end
180
180
  end
181
181
 
182
- context "when frozen" do
183
- before do
184
- person.freeze
185
- end
186
-
187
- it "raises an error" do
188
- expect do
189
- person.name = 'Joe'
190
- end.to raise_error TypeError
191
- end
192
- end
193
-
194
182
  context "when setting the value of an attribute to nil" do
195
183
  it "does not typecast the value" do
196
184
  person.age = nil
metadata CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
4
4
  prerelease: false
5
5
  segments:
6
6
  - 0
7
- - 5
7
+ - 6
8
8
  - 0
9
- version: 0.5.0
9
+ version: 0.6.0
10
10
  platform: ruby
11
11
  authors:
12
12
  - Paper Cavalier
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2011-05-27 00:00:00 +01:00
17
+ date: 2011-05-28 00:00:00 +01:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency