minimapper 0.1.0 → 0.1.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.
- data/README.md +1 -1
- data/lib/minimapper/ar.rb +8 -5
- data/lib/minimapper/entity/attributes.rb +27 -0
- data/lib/minimapper/entity/core.rb +22 -0
- data/lib/minimapper/entity/rails.rb +13 -0
- data/lib/minimapper/entity.rb +8 -45
- data/lib/minimapper/version.rb +1 -1
- data/spec/ar_spec.rb +4 -6
- data/spec/support/shared_examples/mapper.rb +27 -18
- data/unit/entity/core_spec.rb +32 -0
- data/unit/entity_spec.rb +12 -4
- data/unit/memory_spec.rb +4 -6
- metadata +9 -5
data/README.md
CHANGED
@@ -241,11 +241,11 @@ You need mysql and postgres installed (but they do not have to be running) to be
|
|
241
241
|
|
242
242
|
### Next
|
243
243
|
|
244
|
+
* Make "informal" optional. If you only use minimapper/entity/core there is no need for it as a dependency.
|
244
245
|
* Add some way to extend type conversions to keep that part of minimapper small.
|
245
246
|
* Extract entity and model class lookup code from the ar-mapper and reuse it in the memory mapper.
|
246
247
|
* Change the memory mapper to store entity attributes, not entity instances.
|
247
248
|
- Unless this makes it difficult to handle associated data.
|
248
|
-
* Make using Minimapper::Entity optional by providing shared examples of the behavior required by the mappers. Test the mappers with an object implementing only this behavior.
|
249
249
|
|
250
250
|
### Ideas
|
251
251
|
|
data/lib/minimapper/ar.rb
CHANGED
@@ -21,7 +21,7 @@ module Minimapper
|
|
21
21
|
end
|
22
22
|
|
23
23
|
def all
|
24
|
-
record_klass.all.map { |record|
|
24
|
+
record_klass.all.map { |record| entity_for(record) }
|
25
25
|
end
|
26
26
|
|
27
27
|
def first
|
@@ -74,9 +74,9 @@ module Minimapper
|
|
74
74
|
|
75
75
|
# Will attempt to use Project as the enity class when
|
76
76
|
# the mapper class name is AR::ProjectMapper
|
77
|
-
def
|
78
|
-
@
|
79
|
-
@
|
77
|
+
def entity_class
|
78
|
+
@entity_class ||= ("::" + self.class.name.split('::').last.gsub(/Mapper/, '')).constantize
|
79
|
+
@entity_class
|
80
80
|
end
|
81
81
|
|
82
82
|
def find_record_safely(id)
|
@@ -95,7 +95,10 @@ module Minimapper
|
|
95
95
|
|
96
96
|
def entity_for(record)
|
97
97
|
if record
|
98
|
-
|
98
|
+
entity = entity_class.new
|
99
|
+
entity.id = record.id
|
100
|
+
entity.attributes = record.attributes.symbolize_keys
|
101
|
+
entity
|
99
102
|
else
|
100
103
|
nil
|
101
104
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'minimapper/entity/convert'
|
2
|
+
|
3
|
+
module Minimapper
|
4
|
+
module Entity
|
5
|
+
module Attributes
|
6
|
+
def attributes(*list)
|
7
|
+
list.each do |attribute|
|
8
|
+
type = nil
|
9
|
+
|
10
|
+
if attribute.is_a?(Array)
|
11
|
+
attribute, type = attribute
|
12
|
+
end
|
13
|
+
|
14
|
+
define_method(attribute) do
|
15
|
+
instance_variable_get("@#{attribute}")
|
16
|
+
end
|
17
|
+
|
18
|
+
define_method("#{attribute}=") do |value|
|
19
|
+
value = Convert.new(value).to(type)
|
20
|
+
instance_variable_set("@#{attribute}", value)
|
21
|
+
attributes[attribute] = value
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# The core entity API required by minimapper. If your entity
|
2
|
+
# class implements this API, it should work with the data mappers.
|
3
|
+
|
4
|
+
module Minimapper
|
5
|
+
module Entity
|
6
|
+
module Core
|
7
|
+
attr_accessor :id
|
8
|
+
|
9
|
+
def attributes
|
10
|
+
@attributes ||= {}
|
11
|
+
end
|
12
|
+
|
13
|
+
def attributes=(new_attributes)
|
14
|
+
@attributes = attributes.merge(new_attributes)
|
15
|
+
end
|
16
|
+
|
17
|
+
def valid?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/minimapper/entity.rb
CHANGED
@@ -1,55 +1,18 @@
|
|
1
|
-
#
|
2
|
-
# few methods to be present, like valid?, attributes, attributes=.
|
3
|
-
#
|
4
|
-
# I plan to add shared examples that cover the API which minimapper depends upon.
|
5
|
-
#
|
6
|
-
# This class also does some things needed for it to work well with rails.
|
1
|
+
# Look at minimapper/entity/core for the required API.
|
7
2
|
require 'informal'
|
8
|
-
require 'minimapper/entity/
|
3
|
+
require 'minimapper/entity/core'
|
4
|
+
require 'minimapper/entity/attributes'
|
5
|
+
require 'minimapper/entity/rails'
|
9
6
|
|
10
7
|
module Minimapper
|
11
8
|
module Entity
|
12
|
-
|
13
|
-
def attributes(*list)
|
14
|
-
list.each do |attribute|
|
15
|
-
type = nil
|
16
|
-
|
17
|
-
if attribute.is_a?(Array)
|
18
|
-
attribute, type = attribute
|
19
|
-
end
|
20
|
-
|
21
|
-
define_method(attribute) do
|
22
|
-
instance_variable_get("@#{attribute}")
|
23
|
-
end
|
24
|
-
|
25
|
-
define_method("#{attribute}=") do |value|
|
26
|
-
value = Convert.new(value).to(type)
|
27
|
-
instance_variable_set("@#{attribute}", value)
|
28
|
-
attributes[attribute] = value
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
module InstanceMethods
|
35
|
-
def to_param
|
36
|
-
id
|
37
|
-
end
|
38
|
-
|
39
|
-
def persisted?
|
40
|
-
id
|
41
|
-
end
|
42
|
-
|
43
|
-
def attributes
|
44
|
-
@attributes ||= {}
|
45
|
-
end
|
46
|
-
end
|
9
|
+
include Minimapper::Entity::Core
|
47
10
|
|
48
11
|
def self.included(klass)
|
49
12
|
klass.send(:include, Informal::Model)
|
50
|
-
klass.send(:include,
|
51
|
-
klass.send(:extend,
|
52
|
-
klass.attributes
|
13
|
+
klass.send(:include, Minimapper::Entity::Rails)
|
14
|
+
klass.send(:extend, Minimapper::Entity::Attributes)
|
15
|
+
klass.attributes([ :id, :Integer ], [ :created_at, :DateTime ], [ :updated_at, :DateTime ])
|
53
16
|
end
|
54
17
|
end
|
55
18
|
end
|
data/lib/minimapper/version.rb
CHANGED
data/spec/ar_spec.rb
CHANGED
@@ -1,17 +1,15 @@
|
|
1
1
|
require "spec_helper"
|
2
|
-
require "minimapper/entity"
|
2
|
+
require "minimapper/entity/core"
|
3
3
|
require "minimapper/ar"
|
4
4
|
|
5
5
|
class TestEntity
|
6
|
-
include Minimapper::Entity
|
7
|
-
attributes :name, :github_url
|
8
|
-
validates :name, :presence => true
|
6
|
+
include Minimapper::Entity::Core
|
9
7
|
end
|
10
8
|
|
11
9
|
class TestMapper < Minimapper::AR
|
12
10
|
private
|
13
11
|
|
14
|
-
def
|
12
|
+
def entity_class
|
15
13
|
TestEntity
|
16
14
|
end
|
17
15
|
|
@@ -27,7 +25,7 @@ end
|
|
27
25
|
|
28
26
|
describe Minimapper::AR do
|
29
27
|
let(:repository) { TestMapper.new }
|
30
|
-
let(:
|
28
|
+
let(:entity_class) { TestEntity }
|
31
29
|
|
32
30
|
include_examples :mapper
|
33
31
|
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
shared_examples :mapper do
|
2
|
-
# expects repository and
|
2
|
+
# expects repository and entity_class to be defined
|
3
3
|
|
4
4
|
describe "#create" do
|
5
5
|
it "sets an id on the entity" do
|
@@ -23,11 +23,14 @@ shared_examples :mapper do
|
|
23
23
|
entity = build_valid_entity
|
24
24
|
repository.create(entity)
|
25
25
|
repository.last.object_id.should_not == entity.object_id
|
26
|
-
repository.last.name.should == "test"
|
26
|
+
repository.last.attributes[:name].should == "test"
|
27
27
|
end
|
28
28
|
|
29
29
|
it "validates the record before saving" do
|
30
|
-
entity =
|
30
|
+
entity = entity_class.new
|
31
|
+
def entity.valid?
|
32
|
+
false
|
33
|
+
end
|
31
34
|
repository.create(entity).should be_false
|
32
35
|
end
|
33
36
|
end
|
@@ -37,9 +40,9 @@ shared_examples :mapper do
|
|
37
40
|
entity = build_valid_entity
|
38
41
|
repository.create(entity)
|
39
42
|
found_entity = repository.find(entity.id)
|
40
|
-
found_entity.name.should == "test"
|
43
|
+
found_entity.attributes[:name].should == "test"
|
41
44
|
found_entity.id.should == entity.id
|
42
|
-
found_entity.should be_kind_of(Minimapper::Entity)
|
45
|
+
found_entity.should be_kind_of(Minimapper::Entity::Core)
|
43
46
|
end
|
44
47
|
|
45
48
|
it "supports string ids" do
|
@@ -65,9 +68,9 @@ shared_examples :mapper do
|
|
65
68
|
entity = build_valid_entity
|
66
69
|
repository.create(entity)
|
67
70
|
found_entity = repository.find_by_id(entity.id)
|
68
|
-
found_entity.name.should == "test"
|
71
|
+
found_entity.attributes[:name].should == "test"
|
69
72
|
found_entity.id.should == entity.id
|
70
|
-
found_entity.should be_kind_of(Minimapper::Entity)
|
73
|
+
found_entity.should be_kind_of(Minimapper::Entity::Core)
|
71
74
|
end
|
72
75
|
|
73
76
|
it "supports string ids" do
|
@@ -97,7 +100,7 @@ shared_examples :mapper do
|
|
97
100
|
all_entities = repository.all
|
98
101
|
all_entities.map(&:id).should include(first_created_entity.id)
|
99
102
|
all_entities.map(&:id).should include(second_created_entity.id)
|
100
|
-
all_entities.first.should be_kind_of(Minimapper::Entity)
|
103
|
+
all_entities.first.should be_kind_of(Minimapper::Entity::Core)
|
101
104
|
end
|
102
105
|
|
103
106
|
it "does not return the same instances" do
|
@@ -114,7 +117,7 @@ shared_examples :mapper do
|
|
114
117
|
repository.create(first_created_entity)
|
115
118
|
repository.create(build_valid_entity)
|
116
119
|
repository.first.id.should == first_created_entity.id
|
117
|
-
repository.first.should be_kind_of(
|
120
|
+
repository.first.should be_kind_of(entity_class)
|
118
121
|
end
|
119
122
|
|
120
123
|
it "does not return the same instance" do
|
@@ -135,7 +138,7 @@ shared_examples :mapper do
|
|
135
138
|
repository.create(build_valid_entity)
|
136
139
|
repository.create(last_created_entity)
|
137
140
|
repository.last.id.should == last_created_entity.id
|
138
|
-
repository.last.should be_kind_of(
|
141
|
+
repository.last.should be_kind_of(entity_class)
|
139
142
|
end
|
140
143
|
|
141
144
|
it "does not return the same instance" do
|
@@ -163,21 +166,24 @@ shared_examples :mapper do
|
|
163
166
|
entity = build_valid_entity
|
164
167
|
repository.create(entity)
|
165
168
|
|
166
|
-
entity.
|
167
|
-
repository.last.name.should == "test"
|
169
|
+
entity.attributes = { :name => "Updated" }
|
170
|
+
repository.last.attributes[:name].should == "test"
|
168
171
|
|
169
172
|
repository.update(entity)
|
170
173
|
repository.last.id.should == entity.id
|
171
|
-
repository.last.name.should == "Updated"
|
174
|
+
repository.last.attributes[:name].should == "Updated"
|
172
175
|
end
|
173
176
|
|
174
177
|
it "does not update and returns false when the entity isn't valid" do
|
175
178
|
entity = build_valid_entity
|
176
179
|
repository.create(entity)
|
177
|
-
|
180
|
+
|
181
|
+
def entity.valid?
|
182
|
+
false
|
183
|
+
end
|
178
184
|
|
179
185
|
repository.update(entity).should be_false
|
180
|
-
repository.last.name.should == "test"
|
186
|
+
repository.last.attributes[:name].should == "test"
|
181
187
|
end
|
182
188
|
|
183
189
|
it "returns true" do
|
@@ -219,12 +225,13 @@ shared_examples :mapper do
|
|
219
225
|
end
|
220
226
|
|
221
227
|
it "fails when the entity does not have an id" do
|
222
|
-
entity =
|
228
|
+
entity = entity_class.new
|
223
229
|
lambda { repository.delete(entity) }.should raise_error(Minimapper::Common::CanNotFindEntity)
|
224
230
|
end
|
225
231
|
|
226
232
|
it "fails when the entity can not be found" do
|
227
|
-
entity =
|
233
|
+
entity = entity_class.new
|
234
|
+
entity.id = -1
|
228
235
|
lambda { repository.delete(entity) }.should raise_error(Minimapper::Common::CanNotFindEntity)
|
229
236
|
end
|
230
237
|
end
|
@@ -255,6 +262,8 @@ shared_examples :mapper do
|
|
255
262
|
private
|
256
263
|
|
257
264
|
def build_valid_entity
|
258
|
-
|
265
|
+
entity = entity_class.new
|
266
|
+
entity.attributes = { :name => 'test' }
|
267
|
+
entity
|
259
268
|
end
|
260
269
|
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'minimapper/entity/core'
|
2
|
+
|
3
|
+
class BasicEntity
|
4
|
+
include Minimapper::Entity::Core
|
5
|
+
end
|
6
|
+
|
7
|
+
describe Minimapper::Entity::Core do
|
8
|
+
it "can get and set an attributes hash" do
|
9
|
+
entity = BasicEntity.new
|
10
|
+
entity.attributes.should == {}
|
11
|
+
entity.attributes = { :one => 1 }
|
12
|
+
entity.attributes.should == { :one => 1 }
|
13
|
+
end
|
14
|
+
|
15
|
+
it "does not replace the existing hash" do
|
16
|
+
entity = BasicEntity.new
|
17
|
+
entity.attributes = { :one => 1 }
|
18
|
+
entity.attributes = { :two => 2 }
|
19
|
+
entity.attributes.should == { :one => 1, :two => 2 }
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns true for valid?" do
|
23
|
+
entity = BasicEntity.new
|
24
|
+
entity.should be_valid
|
25
|
+
end
|
26
|
+
|
27
|
+
it "responds to id" do
|
28
|
+
entity = BasicEntity.new
|
29
|
+
entity.id = 10
|
30
|
+
entity.id.should == 10
|
31
|
+
end
|
32
|
+
end
|
data/unit/entity_spec.rb
CHANGED
@@ -4,6 +4,12 @@ class TestEntity
|
|
4
4
|
include Minimapper::Entity
|
5
5
|
end
|
6
6
|
|
7
|
+
class TestUser
|
8
|
+
include Minimapper::Entity
|
9
|
+
attributes :name
|
10
|
+
validates :name, :presence => true
|
11
|
+
end
|
12
|
+
|
7
13
|
describe Minimapper::Entity do
|
8
14
|
it "handles base attributes" do
|
9
15
|
entity = TestEntity.new
|
@@ -28,11 +34,13 @@ describe Minimapper::Entity do
|
|
28
34
|
entity.id = "10"
|
29
35
|
entity.id.should == 10
|
30
36
|
end
|
31
|
-
end
|
32
37
|
|
33
|
-
|
34
|
-
|
35
|
-
|
38
|
+
it "applies validations" do
|
39
|
+
user = TestUser.new
|
40
|
+
user.should_not be_valid
|
41
|
+
user.name = "Joe"
|
42
|
+
user.should be_valid
|
43
|
+
end
|
36
44
|
end
|
37
45
|
|
38
46
|
describe Minimapper::Entity, "attributes without type" do
|
data/unit/memory_spec.rb
CHANGED
@@ -1,15 +1,13 @@
|
|
1
1
|
require 'minimapper/memory'
|
2
|
-
require 'minimapper/entity'
|
2
|
+
require 'minimapper/entity/core'
|
3
3
|
|
4
|
-
class
|
5
|
-
include Minimapper::Entity
|
6
|
-
attributes :name
|
7
|
-
validates :name, :presence => true
|
4
|
+
class BasicEntity
|
5
|
+
include Minimapper::Entity::Core
|
8
6
|
end
|
9
7
|
|
10
8
|
describe Minimapper::Memory do
|
11
9
|
let(:repository) { described_class.new }
|
12
|
-
let(:
|
10
|
+
let(:entity_class) { BasicEntity }
|
13
11
|
|
14
12
|
include_examples :mapper
|
15
13
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: minimapper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-11-05 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: informal
|
16
|
-
requirement: &
|
16
|
+
requirement: &70315666068220 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70315666068220
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rake
|
27
|
-
requirement: &
|
27
|
+
requirement: &70315666067440 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70315666067440
|
36
36
|
description: A minimalistic way of separating your models from ORMs like ActiveRecord
|
37
37
|
(by implementing the repository pattern)
|
38
38
|
email:
|
@@ -52,7 +52,10 @@ files:
|
|
52
52
|
- lib/minimapper/ar.rb
|
53
53
|
- lib/minimapper/common.rb
|
54
54
|
- lib/minimapper/entity.rb
|
55
|
+
- lib/minimapper/entity/attributes.rb
|
55
56
|
- lib/minimapper/entity/convert.rb
|
57
|
+
- lib/minimapper/entity/core.rb
|
58
|
+
- lib/minimapper/entity/rails.rb
|
56
59
|
- lib/minimapper/memory.rb
|
57
60
|
- lib/minimapper/repository.rb
|
58
61
|
- lib/minimapper/version.rb
|
@@ -64,6 +67,7 @@ files:
|
|
64
67
|
- spec/support/database_setup.rb
|
65
68
|
- spec/support/shared_examples/mapper.rb
|
66
69
|
- unit/entity/convert_spec.rb
|
70
|
+
- unit/entity/core_spec.rb
|
67
71
|
- unit/entity_spec.rb
|
68
72
|
- unit/memory_spec.rb
|
69
73
|
- unit/repository_spec.rb
|