datamapa 0.0.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.
Files changed (2) hide show
  1. data/lib/datamapa.rb +120 -0
  2. metadata +45 -0
data/lib/datamapa.rb ADDED
@@ -0,0 +1,120 @@
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
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: datamapa
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Yosuke Doi
9
+ autorequire:
10
+ bindir: bin
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
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/datamapa.rb
21
+ homepage: http://rubygems.org/gems/datamapa
22
+ licenses: []
23
+ post_install_message:
24
+ rdoc_options: []
25
+ require_paths:
26
+ - lib
27
+ required_ruby_version: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubyforge_project:
41
+ rubygems_version: 1.8.24
42
+ signing_key:
43
+ specification_version: 3
44
+ summary: Data Mapper using Active Record
45
+ test_files: []