id 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -1
- data/Gemfile.lock +1 -1
- data/README.md +6 -0
- data/id.gemspec +1 -1
- data/lib/id/model/all.rb +1 -0
- data/lib/id/model/builder.rb +45 -0
- data/lib/id/model.rb +15 -3
- data/spec/lib/id/model/association_spec.rb +27 -0
- data/spec/lib/id/model/builder_spec.rb +45 -0
- data/spec/lib/id/model_spec.rb +0 -0
- data/spec/lib/id_spec.rb +0 -25
- metadata +10 -1
data/Gemfile
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
source
|
1
|
+
source 'https://rubygems.org'
|
2
2
|
gemspec
|
data/Gemfile.lock
CHANGED
data/README.md
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
# id
|
2
|
+
### simple models based on hashes
|
3
|
+
|
4
|
+
JSON is a great way to transfer data between systems, and it's easy to parse into a Ruby hash. But sometimes it's nice to have actual methods to call when you want to get attributes from your data, rather than coupling your entire codebase to the hash representation by littering it with calls to `fetch` or `[]`. The same goes for BSON documents stored in Mongo.
|
5
|
+
|
6
|
+
That's where `id` (as in Freud) comes in. You define your model classes using syntax that should look pretty familiar if you've used any popular Ruby ORMs - but `id` is not an ORM. Model objects defined with `id` have a constructor that accepts a hash, and you define the values of this hash that are made readable as fields - but that hash can come from any source.
|
data/id.gemspec
CHANGED
data/lib/id/model/all.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
module Id
|
2
|
+
module Model
|
3
|
+
module Builder
|
4
|
+
|
5
|
+
def initialize(model, data={})
|
6
|
+
@model = model
|
7
|
+
@data = data
|
8
|
+
end
|
9
|
+
|
10
|
+
def build
|
11
|
+
model.new data
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def set(f, value)
|
17
|
+
self.class.new(model, data.merge(f.to_s => ensure_hash(value)))
|
18
|
+
end
|
19
|
+
|
20
|
+
def ensure_hash(value)
|
21
|
+
case value
|
22
|
+
when Id::Model then value.data
|
23
|
+
when Array then value.map { |v| ensure_hash(v) }
|
24
|
+
else value end
|
25
|
+
end
|
26
|
+
|
27
|
+
attr_reader :model, :data
|
28
|
+
|
29
|
+
def self.included(base)
|
30
|
+
base.extend(FieldBuilder)
|
31
|
+
end
|
32
|
+
|
33
|
+
module FieldBuilder
|
34
|
+
|
35
|
+
def field(f)
|
36
|
+
define_method f do |value|
|
37
|
+
set(f, value)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
data/lib/id/model.rb
CHANGED
@@ -1,18 +1,17 @@
|
|
1
1
|
module Id
|
2
2
|
module Model
|
3
|
-
|
4
3
|
attr_reader :data
|
5
4
|
|
6
5
|
def initialize(data)
|
7
6
|
@data = Hash[data.map { |k, v| [k.to_s, v] }]
|
8
7
|
end
|
9
8
|
|
9
|
+
private
|
10
|
+
|
10
11
|
def self.included(base)
|
11
12
|
base.extend(Descriptor)
|
12
13
|
end
|
13
14
|
|
14
|
-
private
|
15
|
-
|
16
15
|
def memoize(f, &b)
|
17
16
|
instance_variable_get("@#{f}") || instance_variable_set("@#{f}", b.call)
|
18
17
|
end
|
@@ -20,14 +19,27 @@ module Id
|
|
20
19
|
module Descriptor
|
21
20
|
def field(f, options={})
|
22
21
|
Field.new(self, f, options).define
|
22
|
+
builder_class.field f
|
23
23
|
end
|
24
24
|
|
25
25
|
def has_one(f, options={})
|
26
26
|
HasOne.new(self, f, options).define
|
27
|
+
builder_class.field f
|
27
28
|
end
|
28
29
|
|
29
30
|
def has_many(f, options={})
|
30
31
|
HasMany.new(self, f, options).define
|
32
|
+
builder_class.field f
|
33
|
+
end
|
34
|
+
|
35
|
+
def builder
|
36
|
+
builder_class.new(self)
|
37
|
+
end
|
38
|
+
|
39
|
+
private
|
40
|
+
|
41
|
+
def builder_class
|
42
|
+
@builder_class ||= Class.new { include Builder }
|
31
43
|
end
|
32
44
|
end
|
33
45
|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Id::Model::Association do
|
4
|
+
|
5
|
+
module Foo
|
6
|
+
module Bar
|
7
|
+
module Baz
|
8
|
+
class Quux
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
let (:model) { stub(name: "Foo::Bar::Baz::Quux") }
|
15
|
+
let (:has_one) { Id::Model::Association.new(model, "yak", {}) }
|
16
|
+
|
17
|
+
describe "hierarchy" do
|
18
|
+
it "builds the class and module hierarchy for the model" do
|
19
|
+
has_one.hierarchy.constants.should eq [
|
20
|
+
Foo::Bar::Baz::Quux,
|
21
|
+
Foo::Bar::Baz,
|
22
|
+
Foo::Bar,
|
23
|
+
Foo
|
24
|
+
]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
class BuilderModel
|
4
|
+
include Id::Model
|
5
|
+
|
6
|
+
field :foo
|
7
|
+
field :bar
|
8
|
+
has_one :nested_builder_model
|
9
|
+
has_many :nested_builder_models
|
10
|
+
|
11
|
+
class NestedBuilderModel
|
12
|
+
include Id::Model
|
13
|
+
|
14
|
+
field :baz
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
module Id
|
20
|
+
describe Model::Builder do
|
21
|
+
|
22
|
+
it 'models can be built using a builder' do
|
23
|
+
BuilderModel.builder.build.should be_a BuilderModel
|
24
|
+
end
|
25
|
+
|
26
|
+
it 'defines chainable setter methods for each field' do
|
27
|
+
model = BuilderModel.builder.foo(4).bar("hello cat").build
|
28
|
+
model.foo.should eq 4
|
29
|
+
model.bar.should eq "hello cat"
|
30
|
+
end
|
31
|
+
|
32
|
+
it 'allows setting of has_one associations using their respective builders' do
|
33
|
+
nested_model = BuilderModel::NestedBuilderModel.builder.baz(:quux).build
|
34
|
+
model = BuilderModel.builder.nested_builder_model(nested_model).build
|
35
|
+
model.nested_builder_model.baz.should eq :quux
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'allows setting of has_many associations using their respective builders' do
|
39
|
+
nested_model = BuilderModel::NestedBuilderModel.builder.baz(:quux).build
|
40
|
+
model = BuilderModel.builder.nested_builder_models([nested_model]).build
|
41
|
+
model.nested_builder_models.first.baz.should eq :quux
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
end
|
File without changes
|
data/spec/lib/id_spec.rb
CHANGED
@@ -74,28 +74,3 @@ describe Id::Model do
|
|
74
74
|
end
|
75
75
|
end
|
76
76
|
|
77
|
-
describe Id::Model::HasOne do
|
78
|
-
|
79
|
-
module Foo
|
80
|
-
module Bar
|
81
|
-
module Baz
|
82
|
-
class Quux
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
let (:model) { stub(name: "Foo::Bar::Baz::Quux") }
|
89
|
-
let (:has_one) { Id::Model::HasOne.new(model, "yak", {}) }
|
90
|
-
|
91
|
-
describe "hierarchy" do
|
92
|
-
it "builds the class and module hierarchy for the model" do
|
93
|
-
has_one.hierarchy.constants.should eq [
|
94
|
-
Foo::Bar::Baz::Quux,
|
95
|
-
Foo::Bar::Baz,
|
96
|
-
Foo::Bar,
|
97
|
-
Foo
|
98
|
-
]
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: id
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -72,6 +72,7 @@ files:
|
|
72
72
|
- Gemfile
|
73
73
|
- Gemfile.lock
|
74
74
|
- LICENSE.md
|
75
|
+
- README.md
|
75
76
|
- id.gemspec
|
76
77
|
- lib/id.rb
|
77
78
|
- lib/id/all.rb
|
@@ -79,9 +80,13 @@ files:
|
|
79
80
|
- lib/id/model.rb
|
80
81
|
- lib/id/model/all.rb
|
81
82
|
- lib/id/model/association.rb
|
83
|
+
- lib/id/model/builder.rb
|
82
84
|
- lib/id/model/field.rb
|
83
85
|
- lib/id/model/has_many.rb
|
84
86
|
- lib/id/model/has_one.rb
|
87
|
+
- spec/lib/id/model/association_spec.rb
|
88
|
+
- spec/lib/id/model/builder_spec.rb
|
89
|
+
- spec/lib/id/model_spec.rb
|
85
90
|
- spec/lib/id_spec.rb
|
86
91
|
- spec/spec_helper.rb
|
87
92
|
homepage: http://rubygems.org/gems/id
|
@@ -109,5 +114,9 @@ signing_key:
|
|
109
114
|
specification_version: 3
|
110
115
|
summary: Simple models based on hashes
|
111
116
|
test_files:
|
117
|
+
- spec/lib/id/model/association_spec.rb
|
118
|
+
- spec/lib/id/model/builder_spec.rb
|
119
|
+
- spec/lib/id/model_spec.rb
|
112
120
|
- spec/lib/id_spec.rb
|
113
121
|
- spec/spec_helper.rb
|
122
|
+
has_rdoc:
|