datamapa 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,19 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+ Session.vim
15
+
16
+ # YARD artifacts
17
+ .yardoc
18
+ _yardoc
19
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in datamapa.gemspec
4
+ gemspec
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ datamapa (0.0.1)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ metaclass (0.0.1)
10
+ minitest (5.0.3)
11
+ mocha (0.14.0)
12
+ metaclass (~> 0.0.1)
13
+
14
+ PLATFORMS
15
+ x86-mingw32
16
+
17
+ DEPENDENCIES
18
+ datamapa!
19
+ minitest
20
+ mocha
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Yosuke Doi
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,4 @@
1
+ datamapa
2
+ ========
3
+
4
+ A minimalistic Data Mapper for removing model dependency on Active Record
@@ -0,0 +1,8 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.pattern = 'spec/**/*_spec.rb'
6
+ end
7
+
8
+ task default: :test
@@ -0,0 +1,23 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'datamapa/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "datamapa"
8
+ spec.version = DataMapa::VERSION
9
+ spec.authors = ["Yosuke Doi"]
10
+ spec.email = ["doinchi@gmail.com"]
11
+ spec.description = 'A minimalistic Data Mapper for removing model dependency on Active Record'
12
+ spec.summary = 'Data Mapper using Active Record'
13
+ spec.homepage = 'http://rubygems.org/gems/datamapa'
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency 'minitest'
22
+ spec.add_development_dependency 'mocha'
23
+ end
@@ -1,120 +1,122 @@
1
- module DataMapa
2
- def self.included(base)
3
- base.extend(ClassMethods)
4
- end
5
-
6
- module ClassMethods
7
- # Declarative methods
8
- def active_record_class(klass)
9
- @ar_class = klass
10
- end
11
-
12
- def model_constructor(method)
13
- @model_constructor = method
14
- end
15
-
16
- def simple_attr(attributes)
17
- @simple_attr = attributes
18
- end
19
-
20
- def ref_attr(attributes)
21
- @ref_attr = attributes
22
- end
23
-
24
- def collection_attr(attributes)
25
- @collection_attr = attributes
26
- end
27
-
28
- # Public methods
29
- def to_ar(model, options={})
30
- ar = model.id ? @ar_class.find(model.id) : @ar_class.new
31
-
32
- o2r_attr(model, ar)
33
- o2r_ref(model, ar)
34
- o2r_collection(model, ar, options[:include]) if options[:include]
35
-
36
- ar
37
- end
38
-
39
- def to_model(ar, options={})
40
- model = @model_constructor.call
41
-
42
- r2o_simple(ar, model)
43
- r2o_ref(ar, model)
44
- r2o_collection(ar, model, options[:include]) if options[:include]
45
-
46
- model
47
- end
48
-
49
- def find!(id)
50
- begin
51
- relational = @ar_class.find(id)
52
- to_model(relational)
53
- rescue ActiveRecord::RecordNotFound
54
- raise DataMapa::RecordNotFoundError
55
- end
56
- end
57
-
58
- def save!(model)
59
- begin
60
- ar = to_ar(model)
61
- ar.save!
62
- model.send(:id=, ar.id)
63
- rescue ActiveRecord::StatementInvalid
64
- raise DataMapa::DuplicateKeyError
65
- end
66
- end
67
-
68
- private
69
-
70
- def r2o_simple(relational, object)
71
- @simple_attr.each do |attr|
72
- setter = "#{attr.to_s.chomp('?')}="
73
- object.send(setter, relational.send(attr))
74
- end
75
- end
76
-
77
- def r2o_ref(relational, object)
78
- @ref_attr.each do |attr, mapper|
79
- setter = "#{attr}="
80
- object.send(setter, mapper.to_model(relational.send(attr)))
81
- end
82
- end
83
-
84
- def r2o_collection(ar, model, attributes)
85
- attributes.each do |attr|
86
- ar_items = ar.send(attr)
87
- model_items = ar_items.map {|i| @collection_attr[attr].to_model(i)}
88
- model.send("#{attr}=", model_items)
89
- end
90
- end
91
-
92
- def o2r_attr(object, relational)
93
- @simple_attr.each do |attr|
94
- relational.send("#{attr.to_s.chomp('?')}=", object.send(attr))
95
- end
96
- end
97
-
98
- def o2r_ref(object, relational)
99
- @ref_attr.each_key do |attr|
100
- ref = object.send(attr)
101
- relational.send("#{attr.to_s.chomp('?')}_id=", ref.id) unless ref.nil?
102
- end
103
- end
104
-
105
- def o2r_collection(object, relational, attributes)
106
- attributes.each do |attr|
107
- collection = object.send(attr).map do |item|
108
- @collection_attr[attr].to_ar(item)
109
- end
110
- relational.send("#{attr}=", collection)
111
- end
112
- end
113
- end
114
-
115
- class RecordNotFoundError < StandardError
116
- end
117
-
118
- class DuplicateKeyError < StandardError
119
- end
120
- end
1
+ require "datamapa/version"
2
+
3
+ module DataMapa
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ # Declarative methods
10
+ def active_record_class(klass)
11
+ @ar_class = klass
12
+ end
13
+
14
+ def model_constructor(method)
15
+ @model_constructor = method
16
+ end
17
+
18
+ def simple_attr(attributes)
19
+ @simple_attr = attributes
20
+ end
21
+
22
+ def ref_attr(attributes)
23
+ @ref_attr = attributes
24
+ end
25
+
26
+ def collection_attr(attributes)
27
+ @collection_attr = attributes
28
+ end
29
+
30
+ # Public methods
31
+ def to_ar(model, options={})
32
+ ar = model.id ? @ar_class.find(model.id) : @ar_class.new
33
+
34
+ o2r_attr(model, ar)
35
+ o2r_ref(model, ar)
36
+ o2r_collection(model, ar, options[:include]) if options[:include]
37
+
38
+ ar
39
+ end
40
+
41
+ def to_model(ar, options={})
42
+ model = @model_constructor.call
43
+
44
+ r2o_simple(ar, model)
45
+ r2o_ref(ar, model)
46
+ r2o_collection(ar, model, options[:include]) if options[:include]
47
+
48
+ model
49
+ end
50
+
51
+ def find!(id)
52
+ begin
53
+ relational = @ar_class.find(id)
54
+ to_model(relational)
55
+ rescue ActiveRecord::RecordNotFound
56
+ raise DataMapa::RecordNotFoundError
57
+ end
58
+ end
59
+
60
+ def save!(model)
61
+ begin
62
+ ar = to_ar(model)
63
+ ar.save!
64
+ model.send(:id=, ar.id)
65
+ rescue ActiveRecord::StatementInvalid
66
+ raise DataMapa::DuplicateKeyError
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ def r2o_simple(relational, object)
73
+ @simple_attr.each do |attr|
74
+ setter = "#{attr.to_s.chomp('?')}="
75
+ object.send(setter, relational.send(attr))
76
+ end
77
+ end
78
+
79
+ def r2o_ref(relational, object)
80
+ @ref_attr.each do |attr, mapper|
81
+ setter = "#{attr}="
82
+ object.send(setter, mapper.to_model(relational.send(attr)))
83
+ end
84
+ end
85
+
86
+ def r2o_collection(ar, model, attributes)
87
+ attributes.each do |attr|
88
+ ar_items = ar.send(attr)
89
+ model_items = ar_items.map {|i| @collection_attr[attr].to_model(i)}
90
+ model.send("#{attr}=", model_items)
91
+ end
92
+ end
93
+
94
+ def o2r_attr(object, relational)
95
+ @simple_attr.each do |attr|
96
+ relational.send("#{attr.to_s.chomp('?')}=", object.send(attr))
97
+ end
98
+ end
99
+
100
+ def o2r_ref(object, relational)
101
+ @ref_attr.each_key do |attr|
102
+ ref = object.send(attr)
103
+ relational.send("#{attr.to_s.chomp('?')}_id=", ref.id) unless ref.nil?
104
+ end
105
+ end
106
+
107
+ def o2r_collection(object, relational, attributes)
108
+ attributes.each do |attr|
109
+ collection = object.send(attr).map do |item|
110
+ @collection_attr[attr].to_ar(item)
111
+ end
112
+ relational.send("#{attr}=", collection)
113
+ end
114
+ end
115
+ end
116
+
117
+ class RecordNotFoundError < StandardError
118
+ end
119
+
120
+ class DuplicateKeyError < StandardError
121
+ end
122
+ end
@@ -0,0 +1,3 @@
1
+ module DataMapa
2
+ VERSION = "0.0.2"
3
+ end
@@ -0,0 +1,180 @@
1
+ require 'minitest/autorun'
2
+ require 'mocha/setup'
3
+ require 'datamapa'
4
+
5
+ describe DataMapa do
6
+
7
+ def class_with_attributes(attributes)
8
+ Class.new do
9
+ attributes.each do |attr|
10
+ attr_accessor attr
11
+ end
12
+ end
13
+ end
14
+
15
+ def mapper_class(ar_class, model_class, attributes)
16
+ Class.new do
17
+ include DataMapa
18
+
19
+ active_record_class ar_class
20
+ model_constructor model_class.method(:new)
21
+ simple_attr attributes[:simple] || []
22
+ ref_attr attributes[:ref] || {}
23
+ collection_attr attributes[:collection] || {}
24
+ end
25
+ end
26
+
27
+ let (:any_object) { Object.new }
28
+
29
+ describe "simple attribute" do
30
+ let(:ar_class) { class_with_attributes([:id, :a1]) }
31
+ let(:model_class) { class_with_attributes([:id, :a1]) }
32
+ let(:mapper) { mapper_class(
33
+ ar_class, model_class,
34
+ simple: [:id, :a1]
35
+ ) }
36
+
37
+ it "converts to model" do
38
+ ar = stub(id: 1, a1: 'any string')
39
+
40
+ model = mapper.to_model(ar)
41
+
42
+ model.id.must_equal ar.id
43
+ model.a1.must_equal ar.a1
44
+ end
45
+
46
+ it "converts to ar" do
47
+ model = stub(id: nil, a1: 'any string')
48
+
49
+ ar = mapper.to_ar(model)
50
+
51
+ ar.id.must_equal model.id
52
+ ar.a1.must_equal model.a1
53
+ end
54
+ end
55
+
56
+ describe "ref attribute" do
57
+ let(:ar_class) { class_with_attributes([:id, :a1_id]) }
58
+ let(:model_class) { class_with_attributes([:id, :a1]) }
59
+ let(:a1_model) { any_object }
60
+ let(:mapper) { mapper_class(
61
+ ar_class, model_class,
62
+ simple: [:id],
63
+ ref: { a1: stub(to_model: a1_model) }
64
+ ) }
65
+
66
+ it "converts to model without option" do
67
+ ar = stub(id: 1, a1: nil)
68
+
69
+ model = mapper.to_model(ar)
70
+
71
+ model.id.must_equal ar.id
72
+ model.a1.must_equal a1_model
73
+ end
74
+
75
+ it "converts to AR" do
76
+ model = stub(id: nil, a1: stub(id: 10))
77
+
78
+ ar = mapper.to_ar(model)
79
+
80
+ ar.id.must_equal model.id
81
+ ar.a1_id.must_equal model.a1.id
82
+ end
83
+ end
84
+
85
+ describe "collection attribute" do
86
+ let(:ar_class) { class_with_attributes([:id, :a1]) }
87
+ let(:model_class) { class_with_attributes([:id, :a1]) }
88
+ let(:a1_model) { any_object }
89
+ let(:a1_ar) { any_object }
90
+ let(:mapper) { mapper_class(
91
+ ar_class, model_class,
92
+ simple: [:id],
93
+ collection: {a1: stub(to_model: a1_model, to_ar: a1_ar)}
94
+ ) }
95
+
96
+ it "converts to model with option" do
97
+ ar = stub(id: 1, a1: [Object.new, Object.new])
98
+
99
+ model = mapper.to_model(ar, include: [:a1])
100
+
101
+ model.id.must_equal ar.id
102
+ model.a1[0].must_equal a1_model
103
+ model.a1[1].must_equal a1_model
104
+ end
105
+
106
+ it "does not convert to model without option" do
107
+ ar = stub(id: 1, a1: [Object.new, Object.new])
108
+
109
+ model = mapper.to_model(ar)
110
+
111
+ model.id.must_equal ar.id
112
+ model.a1.must_equal nil
113
+ end
114
+
115
+ it "converts to AR with option" do
116
+ model = stub(id: nil, a1: [Object.new, Object.new])
117
+
118
+ ar = mapper.to_ar(model, include: [:a1])
119
+
120
+ ar.id.must_equal model.id
121
+ ar.a1[0].must_equal a1_ar
122
+ ar.a1[1].must_equal a1_ar
123
+ end
124
+
125
+ it "does not convert to AR without option" do
126
+ model = stub(id: nil, a1: [Object.new, Object.new])
127
+
128
+ ar = mapper.to_ar(model)
129
+
130
+ ar.id.must_equal model.id
131
+ ar.a1.must_equal nil
132
+ end
133
+ end
134
+
135
+ describe "attribute in AR only" do
136
+ let(:ar_class) { class_with_attributes([:id, :a1]) }
137
+ let(:model_class) { class_with_attributes([:id]) }
138
+ let(:mapper) { mapper_class(ar_class, model_class, simple: [:id]) }
139
+
140
+ it "converts to model" do
141
+ ar = stub(id: 1, a1: 'any string')
142
+
143
+ model = mapper.to_model(ar)
144
+
145
+ model.id.must_equal ar.id
146
+ end
147
+
148
+ it "converts to AR" do
149
+ model = stub(id: nil)
150
+
151
+ ar = mapper.to_ar(model)
152
+
153
+ ar.id.must_equal model.id
154
+ ar.a1.must_equal nil
155
+ end
156
+ end
157
+
158
+ describe "attribute in model only" do
159
+ let(:ar_class) { class_with_attributes([:id]) }
160
+ let(:model_class) { class_with_attributes([:id, :a1]) }
161
+ let(:mapper) { mapper_class(ar_class, model_class, simple: [:id]) }
162
+
163
+ it "converts to model" do
164
+ ar = stub(id: 1)
165
+
166
+ model = mapper.to_model(ar)
167
+
168
+ model.id.must_equal ar.id
169
+ model.a1.must_equal nil
170
+ end
171
+
172
+ it "converts to AR" do
173
+ model = stub(id: nil, a1: 'any string')
174
+
175
+ ar = mapper.to_ar(model)
176
+
177
+ ar.id.must_equal model.id
178
+ end
179
+ end
180
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: datamapa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,17 +9,60 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-06-07 00:00:00.000000000 Z
13
- dependencies: []
14
- description: Inverts dependency from model to persistence
15
- email: doinchi@gmail.com
12
+ date: 2013-06-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: minitest
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: mocha
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ description: A minimalistic Data Mapper for removing model dependency on Active Record
47
+ email:
48
+ - doinchi@gmail.com
16
49
  executables: []
17
50
  extensions: []
18
51
  extra_rdoc_files: []
19
52
  files:
53
+ - .gitignore
54
+ - Gemfile
55
+ - Gemfile.lock
56
+ - LICENSE.txt
57
+ - README.md
58
+ - Rakefile
59
+ - datamapa.gemspec
20
60
  - lib/datamapa.rb
61
+ - lib/datamapa/version.rb
62
+ - spec/datamapa/datamapa_spec.rb
21
63
  homepage: http://rubygems.org/gems/datamapa
22
- licenses: []
64
+ licenses:
65
+ - MIT
23
66
  post_install_message:
24
67
  rdoc_options: []
25
68
  require_paths:
@@ -42,4 +85,5 @@ rubygems_version: 1.8.24
42
85
  signing_key:
43
86
  specification_version: 3
44
87
  summary: Data Mapper using Active Record
45
- test_files: []
88
+ test_files:
89
+ - spec/datamapa/datamapa_spec.rb