datamappify 0.50.0 → 0.51.0
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/README.md +78 -4
- data/lib/datamappify/data/criteria/active_record/find_multiple.rb +28 -0
- data/lib/datamappify/data/criteria/common.rb +28 -8
- data/lib/datamappify/data/criteria/relational/find_multiple.rb +62 -3
- data/lib/datamappify/data/criteria/sequel/find_multiple.rb +31 -0
- data/lib/datamappify/data/errors.rb +3 -0
- data/lib/datamappify/data/mapper/attribute.rb +81 -3
- data/lib/datamappify/data/mapper.rb +12 -12
- data/lib/datamappify/data/provider/active_record.rb +20 -5
- data/lib/datamappify/data/provider/common_provider.rb +2 -0
- data/lib/datamappify/data/provider/sequel.rb +25 -6
- data/lib/datamappify/data/record.rb +18 -5
- data/lib/datamappify/entity/composable.rb +63 -7
- data/lib/datamappify/entity/relation.rb +1 -1
- data/lib/datamappify/repository/inheritable.rb +28 -0
- data/lib/datamappify/repository/query_method/find_multiple.rb +1 -7
- data/lib/datamappify/repository/query_method/method.rb +2 -2
- data/lib/datamappify/repository/query_methods.rb +8 -4
- data/lib/datamappify/repository.rb +2 -0
- data/lib/datamappify/version.rb +1 -1
- data/spec/entity/composable_spec.rb +34 -11
- data/spec/entity/inheritance_spec.rb +33 -0
- data/spec/entity/relation_spec.rb +11 -9
- data/spec/repository/finders_spec.rb +185 -7
- data/spec/support/entities/admin_user.rb +5 -0
- data/spec/support/entities/computer.rb +2 -0
- data/spec/support/entities/computer_hardware.rb +4 -0
- data/spec/support/entities/computer_software.rb +3 -0
- data/spec/support/repositories/active_record/admin_user_repository.rb +5 -0
- data/spec/support/repositories/sequel/admin_user_repository.rb +5 -0
- data/spec/support/tables/active_record.rb +1 -0
- data/spec/support/tables/sequel.rb +1 -0
- data/spec/unit/entity/relation_spec.rb +12 -2
- metadata +11 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f9765005a9b047c0dabab75eeb3da7997761c57d
|
4
|
+
data.tar.gz: c6747c591e913b7565a730ea7192703991aaf2b6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 64566dfe4f603db5104657ca9416aef1d96f4b0327de25c0c9a36a68285b3dcf049efd2c39381f5f4f2ab7b781509c13f0c4ef27b02066e9b634e5cd23c56720
|
7
|
+
data.tar.gz: 0bc81a94c2c52c1b3da152d79f39405be5050e2242c526d628650591a4e741250f5d47136c93ef96a2a1f63f6c264200754ad603ea41954aafaffb2ce2f91cda
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
## master
|
2
2
|
|
3
|
+
## 0.51.0 [2013-06-17]
|
4
|
+
|
5
|
+
- Enhanced `find` for searching specific attributes.
|
6
|
+
- Added support for repository inheritance.
|
7
|
+
- `attributes_from` now copies validations as well!
|
8
|
+
- `find` now raises an exception if the arguments contain an unknown attribute key.
|
9
|
+
|
3
10
|
## 0.50.0 [2013-05-30]
|
4
11
|
|
5
12
|
- Added `all` to repository.
|
data/README.md
CHANGED
@@ -50,16 +50,50 @@ class User
|
|
50
50
|
attribute :driver_license, String
|
51
51
|
attribute :health_care, String
|
52
52
|
|
53
|
-
# Nested entity composition - composing the entity with attributes from other entities
|
53
|
+
# Nested entity composition - composing the entity with attributes and validations from other entities
|
54
|
+
#
|
55
|
+
# class Job
|
56
|
+
# include Datamappify::Entity
|
57
|
+
#
|
58
|
+
# attributes :title, String
|
59
|
+
# validates :title, :presence => true
|
60
|
+
# end
|
61
|
+
#
|
62
|
+
# class User
|
63
|
+
# # ...
|
64
|
+
# attributes_from Job
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# essentially equals:
|
68
|
+
#
|
69
|
+
# class User
|
70
|
+
# # ...
|
71
|
+
# attributes :title, String
|
72
|
+
# validates :title, :presence => true
|
73
|
+
# end
|
54
74
|
attributes_from Job
|
55
75
|
|
56
76
|
# optionally you may prefix the attributes, so that:
|
57
77
|
#
|
58
|
-
#
|
78
|
+
# class Hobby
|
79
|
+
# include Datamappify::Entity
|
80
|
+
#
|
81
|
+
# attributes :name, String
|
82
|
+
# validates :name, :presence => true
|
83
|
+
# end
|
84
|
+
#
|
85
|
+
# class User
|
86
|
+
# # ...
|
87
|
+
# attributes_from Hobby, :prefix_with => :hobby
|
88
|
+
# end
|
59
89
|
#
|
60
90
|
# becomes:
|
61
91
|
#
|
62
|
-
#
|
92
|
+
# class User
|
93
|
+
# # ...
|
94
|
+
# attributes :hobby_name, String
|
95
|
+
# validates :hobby_name, :presence => true
|
96
|
+
# end
|
63
97
|
attributes_from Hobby, :prefix_with => :hobby
|
64
98
|
|
65
99
|
# Entity reference
|
@@ -85,6 +119,18 @@ class User
|
|
85
119
|
end
|
86
120
|
```
|
87
121
|
|
122
|
+
Inheritance is supported for entities, for example:
|
123
|
+
|
124
|
+
```ruby
|
125
|
+
class AdminUser < User
|
126
|
+
attribute :level, Integer
|
127
|
+
end
|
128
|
+
|
129
|
+
class GuestUser < User
|
130
|
+
attribute :expiry, DateTime
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
88
134
|
#### Lazy loading
|
89
135
|
|
90
136
|
Datamappify supports attribute lazy loading via the `Lazy` module.
|
@@ -126,6 +172,24 @@ class UserRepository
|
|
126
172
|
end
|
127
173
|
```
|
128
174
|
|
175
|
+
Inheritance is supported for repositories when your data structure is based on STI ([Single Table Inheritance](http://en.wikipedia.org/wiki/Single_Table_Inheritance)), for example:
|
176
|
+
|
177
|
+
```ruby
|
178
|
+
class AdminUserRepository < UserRepository
|
179
|
+
for_entity AdminUser
|
180
|
+
end
|
181
|
+
|
182
|
+
class GuestUserRepository < UserRepository
|
183
|
+
for_entity GuestUser
|
184
|
+
|
185
|
+
map_attribute :expiry, 'ActiveRecord::User#expiry_date'
|
186
|
+
end
|
187
|
+
```
|
188
|
+
|
189
|
+
In the above example, both repositories deal with the `User` data model.
|
190
|
+
|
191
|
+
### Repository APIs
|
192
|
+
|
129
193
|
_More repository APIs are being added, below is a list of the currently implemented APIs._
|
130
194
|
|
131
195
|
#### Retrieving an entity
|
@@ -146,12 +210,22 @@ UserRepository.exists?(user)
|
|
146
210
|
|
147
211
|
#### Retrieving all entities
|
148
212
|
|
149
|
-
Returns an array of
|
213
|
+
Returns an array of entities.
|
150
214
|
|
151
215
|
```ruby
|
152
216
|
users = UserRepository.all
|
153
217
|
```
|
154
218
|
|
219
|
+
#### Searching entities
|
220
|
+
|
221
|
+
Returns an array of entities.
|
222
|
+
|
223
|
+
```ruby
|
224
|
+
users = UserRepository.find(:first_name => 'Fred', :driver_license => 'AABBCCDD')
|
225
|
+
```
|
226
|
+
|
227
|
+
_Note: it does not currently support searching attributes from different data providers._
|
228
|
+
|
155
229
|
#### Saving/updating entities
|
156
230
|
|
157
231
|
Pass in an entity.
|
@@ -5,6 +5,34 @@ module Datamappify
|
|
5
5
|
module Criteria
|
6
6
|
module ActiveRecord
|
7
7
|
class FindMultiple < Relational::FindMultiple
|
8
|
+
private
|
9
|
+
|
10
|
+
# @return [Array]
|
11
|
+
def records
|
12
|
+
source_class.joins(@secondaries.map(&:source_key)).where(
|
13
|
+
structured_criteria(primaries, secondaries)
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
# @param primaries [Array<Attribute>]
|
18
|
+
#
|
19
|
+
# @param secondaries [Array<Attribute>]
|
20
|
+
#
|
21
|
+
# @return [Hash]
|
22
|
+
def structured_criteria(primaries, secondaries)
|
23
|
+
_criteria = {}
|
24
|
+
|
25
|
+
primaries.each do |primary|
|
26
|
+
_criteria[primary.source_attribute_key] = primary.value
|
27
|
+
end
|
28
|
+
|
29
|
+
secondaries.each do |secondary|
|
30
|
+
_criteria[secondary.source_table] ||= {}
|
31
|
+
_criteria[secondary.source_table][secondary.source_attribute_key] = secondary.value
|
32
|
+
end
|
33
|
+
|
34
|
+
_criteria
|
35
|
+
end
|
8
36
|
end
|
9
37
|
end
|
10
38
|
end
|
@@ -41,11 +41,19 @@ module Datamappify
|
|
41
41
|
|
42
42
|
protected
|
43
43
|
|
44
|
+
# Name of the default source class, e.g. +"User"+,
|
45
|
+
# it is determined from either the PK or the entity
|
46
|
+
#
|
47
|
+
# @return [String]
|
48
|
+
def default_source_class_name
|
49
|
+
@default_source_class_name ||= pk ? pk.source_class_name : entity.class.name.demodulize
|
50
|
+
end
|
51
|
+
|
44
52
|
# Key name of either the primary key (e.g. +id+) or foreign key (e.g. +user_id+)
|
45
53
|
#
|
46
54
|
# @return [Symbol]
|
47
55
|
def key_name
|
48
|
-
primary_record? ? :id :
|
56
|
+
primary_record? ? :id : any_attribute.primary_reference_key
|
49
57
|
end
|
50
58
|
|
51
59
|
# The value of {#key_name}
|
@@ -66,7 +74,7 @@ module Datamappify
|
|
66
74
|
#
|
67
75
|
# @return [Boolean]
|
68
76
|
def primary_record?
|
69
|
-
source_class.name.demodulize ==
|
77
|
+
source_class.name.demodulize == default_source_class_name
|
70
78
|
end
|
71
79
|
|
72
80
|
# Ignores the current Criteria's operation if there is no dirty attributes
|
@@ -80,15 +88,17 @@ module Datamappify
|
|
80
88
|
#
|
81
89
|
# @return [Hash]
|
82
90
|
def attributes_and_values
|
83
|
-
|
91
|
+
@attributes_and_values ||= begin
|
92
|
+
hash = {}
|
84
93
|
|
85
|
-
|
86
|
-
|
87
|
-
|
94
|
+
attributes.each do |attribute|
|
95
|
+
unless ignore_attribute?(attribute)
|
96
|
+
hash[attribute.source_attribute_name] = entity.send(attribute.name)
|
97
|
+
end
|
88
98
|
end
|
89
|
-
end
|
90
99
|
|
91
|
-
|
100
|
+
hash
|
101
|
+
end
|
92
102
|
end
|
93
103
|
|
94
104
|
# Stores the attribute value in {Mapper::Attribute} for later use
|
@@ -100,6 +110,16 @@ module Datamappify
|
|
100
110
|
end
|
101
111
|
end
|
102
112
|
|
113
|
+
# @return [Attribute]
|
114
|
+
def any_attribute
|
115
|
+
@any_attribute ||= attributes.first
|
116
|
+
end
|
117
|
+
|
118
|
+
# @return [Attribute]
|
119
|
+
def pk
|
120
|
+
@pk ||= attributes.find { |attribute| attribute.key == :id }
|
121
|
+
end
|
122
|
+
|
103
123
|
private
|
104
124
|
|
105
125
|
# Ignores the attribute if it isn't dirty or if it's a primary key
|
@@ -5,8 +5,22 @@ module Datamappify
|
|
5
5
|
class FindMultiple < Common
|
6
6
|
alias_method :entity_class, :entity
|
7
7
|
|
8
|
+
attr_reader :primaries, :secondaries, :structured_criteria
|
9
|
+
|
10
|
+
def initialize(*args)
|
11
|
+
super
|
12
|
+
|
13
|
+
@primaries = []
|
14
|
+
@secondaries = []
|
15
|
+
|
16
|
+
updated_attributes.each do |attribute|
|
17
|
+
collector = attribute.primary_attribute? ? @primaries : @secondaries
|
18
|
+
collector << attribute
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# @return [void]
|
8
23
|
def perform
|
9
|
-
records = source_class.where(criteria)
|
10
24
|
records.map do |record|
|
11
25
|
entity = entity_class.new
|
12
26
|
update_entity(entity, record)
|
@@ -16,11 +30,56 @@ module Datamappify
|
|
16
30
|
|
17
31
|
private
|
18
32
|
|
19
|
-
|
33
|
+
# @return [Array]
|
34
|
+
def updated_attributes
|
35
|
+
unless criteria.keys & attributes.map(&:key) == criteria.keys
|
36
|
+
raise EntityAttributeInvalid
|
37
|
+
end
|
38
|
+
|
39
|
+
@updated_attributes ||= attributes.select do |attribute|
|
40
|
+
attribute.value = criteria[attribute.key]
|
41
|
+
criteria.keys.include?(attribute.key)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
# @param entity [Entity]
|
46
|
+
#
|
47
|
+
# @param record [Class]
|
48
|
+
#
|
49
|
+
# @return [void]
|
50
|
+
def update_entity(entity, primary_record)
|
20
51
|
attributes.each do |attribute|
|
21
|
-
|
52
|
+
record = data_record_for(attribute, primary_record)
|
53
|
+
value = record_value_for(attribute, record)
|
54
|
+
|
55
|
+
entity.send("#{attribute.name}=", value)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# @param attribute [Attribute]
|
60
|
+
#
|
61
|
+
# @param primary_record [Class]
|
62
|
+
# an ORM model object (ActiveRecord or Sequel, etc)
|
63
|
+
#
|
64
|
+
# @return [Object]
|
65
|
+
# an ORM model object (ActiveRecord or Sequel, etc)
|
66
|
+
def data_record_for(attribute, primary_record)
|
67
|
+
if attribute.primary_attribute?
|
68
|
+
primary_record
|
69
|
+
else
|
70
|
+
primary_record.send(attribute.source_key)
|
22
71
|
end
|
23
72
|
end
|
73
|
+
|
74
|
+
# @param attribute [Attribute]
|
75
|
+
#
|
76
|
+
# @param record [Class]
|
77
|
+
# an ORM model object (ActiveRecord or Sequel, etc)
|
78
|
+
#
|
79
|
+
# @return [any]
|
80
|
+
def record_value_for(attribute, record)
|
81
|
+
record.nil? ? nil : record.send(attribute.source_attribute_name)
|
82
|
+
end
|
24
83
|
end
|
25
84
|
end
|
26
85
|
end
|
@@ -5,6 +5,37 @@ module Datamappify
|
|
5
5
|
module Criteria
|
6
6
|
module Sequel
|
7
7
|
class FindMultiple < Relational::FindMultiple
|
8
|
+
private
|
9
|
+
|
10
|
+
# @return [Array]
|
11
|
+
def records
|
12
|
+
query_builder = source_class
|
13
|
+
|
14
|
+
secondaries.each do |secondary|
|
15
|
+
query_builder = query_builder.join(secondary.source_table, secondary.primary_reference_key => :id)
|
16
|
+
end
|
17
|
+
|
18
|
+
query_builder.where(structured_criteria(primaries, secondaries))
|
19
|
+
end
|
20
|
+
|
21
|
+
# @param primaries [Array<Attribute>]
|
22
|
+
#
|
23
|
+
# @param secondaries [Array<Attribute>]
|
24
|
+
#
|
25
|
+
# @return [Hash]
|
26
|
+
def structured_criteria(primaries, secondaries)
|
27
|
+
_criteria = {}
|
28
|
+
|
29
|
+
primaries.each do |primary|
|
30
|
+
_criteria[primary.source_attribute_key] = primary.value
|
31
|
+
end
|
32
|
+
|
33
|
+
secondaries.each do |secondary|
|
34
|
+
_criteria[:"#{secondary.source_table}__#{secondary.source_attribute_name}"] = secondary.value
|
35
|
+
end
|
36
|
+
|
37
|
+
_criteria
|
38
|
+
end
|
8
39
|
end
|
9
40
|
end
|
10
41
|
end
|
@@ -20,6 +20,9 @@ module Datamappify
|
|
20
20
|
# @return [String]
|
21
21
|
attr_reader :source_attribute_name
|
22
22
|
|
23
|
+
# @return [Class]
|
24
|
+
attr_reader :primary_source_class
|
25
|
+
|
23
26
|
# @return [any]
|
24
27
|
attr_accessor :value
|
25
28
|
|
@@ -29,23 +32,98 @@ module Datamappify
|
|
29
32
|
# @param source [String]
|
30
33
|
# data provider, class and attribute,
|
31
34
|
# e.g. "ActiveRecord::User#surname"
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
+
#
|
36
|
+
# @param primary_source_class [Class]
|
37
|
+
def initialize(name, source, primary_source_class)
|
38
|
+
@key = name
|
39
|
+
@name = name.to_s
|
40
|
+
@primary_source_class = primary_source_class
|
35
41
|
|
36
42
|
@provider_name, @source_class_name, @source_attribute_name = parse_source(source)
|
43
|
+
|
44
|
+
unless primary_attribute? || external_attribute?
|
45
|
+
Record.build_association(self, primary_source_class)
|
46
|
+
end
|
37
47
|
end
|
38
48
|
|
49
|
+
# @example
|
50
|
+
#
|
51
|
+
# UserComment
|
52
|
+
#
|
39
53
|
# @return [Class]
|
40
54
|
def source_class
|
41
55
|
@source_class ||= Record.find_or_build(provider_name, source_class_name)
|
42
56
|
end
|
43
57
|
|
58
|
+
# @example
|
59
|
+
#
|
60
|
+
# "user_comment"
|
61
|
+
#
|
62
|
+
# @return [String]
|
63
|
+
def source_name
|
64
|
+
@source_name ||= source_class_name.underscore
|
65
|
+
end
|
66
|
+
|
67
|
+
# @example
|
68
|
+
#
|
69
|
+
# :user_comment
|
70
|
+
#
|
71
|
+
# @return [Symbol]
|
72
|
+
def source_key
|
73
|
+
@source_key ||= source_name.to_sym
|
74
|
+
end
|
75
|
+
|
76
|
+
# @example
|
77
|
+
#
|
78
|
+
# :title
|
79
|
+
#
|
80
|
+
# @return [Symbol]
|
81
|
+
def source_attribute_key
|
82
|
+
@source_attribute_key ||= source_attribute_name.to_sym
|
83
|
+
end
|
84
|
+
|
85
|
+
# @example
|
86
|
+
#
|
87
|
+
# :user_comments
|
88
|
+
#
|
89
|
+
# @return [Symbol]
|
90
|
+
def source_table
|
91
|
+
@source_table ||= source_class_name.pluralize.underscore.to_sym
|
92
|
+
end
|
93
|
+
|
44
94
|
# @return [Boolean]
|
45
95
|
def primary_key?
|
46
96
|
source_attribute_name == 'id'
|
47
97
|
end
|
48
98
|
|
99
|
+
# @return [Boolean]
|
100
|
+
def primary_attribute?
|
101
|
+
provider_name == primary_provider_name && primary_source_class == source_class
|
102
|
+
end
|
103
|
+
|
104
|
+
# External attribute is from a different data provider than the primary data provider
|
105
|
+
#
|
106
|
+
# @return [Boolean]
|
107
|
+
def external_attribute?
|
108
|
+
provider_name != primary_provider_name
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [String]
|
112
|
+
def primary_provider_name
|
113
|
+
@primary_provider_name ||= primary_source_class.parent.to_s.demodulize
|
114
|
+
end
|
115
|
+
|
116
|
+
# Foreign key of the primary record, useful for joins
|
117
|
+
#
|
118
|
+
# @example
|
119
|
+
#
|
120
|
+
# :user_id
|
121
|
+
#
|
122
|
+
# @return [Symbol]
|
123
|
+
def primary_reference_key
|
124
|
+
@primary_reference_key ||= :"#{primary_source_class.to_s.demodulize.underscore}_id"
|
125
|
+
end
|
126
|
+
|
49
127
|
private
|
50
128
|
|
51
129
|
# @return [Array<String>]
|
@@ -10,6 +10,9 @@ module Datamappify
|
|
10
10
|
# @return [String]
|
11
11
|
attr_accessor :default_provider_name
|
12
12
|
|
13
|
+
# @return [String]
|
14
|
+
attr_writer :default_source_class_name
|
15
|
+
|
13
16
|
# @return [Hash]
|
14
17
|
# attribute name to source mapping as specified in {Repository::MappingDSL#map_attribute}
|
15
18
|
attr_accessor :custom_mapping
|
@@ -24,6 +27,8 @@ module Datamappify
|
|
24
27
|
@default_provider ||= Provider.const_get(default_provider_name)
|
25
28
|
end
|
26
29
|
|
30
|
+
# @param provider_name [String]
|
31
|
+
#
|
27
32
|
# @return [Module]
|
28
33
|
def provider(provider_name)
|
29
34
|
Provider.const_get(provider_name)
|
@@ -31,12 +36,12 @@ module Datamappify
|
|
31
36
|
|
32
37
|
# @return [Class]
|
33
38
|
def default_source_class
|
34
|
-
@default_source_class ||= default_provider.find_or_build_record_class(
|
39
|
+
@default_source_class ||= default_provider.find_or_build_record_class(default_source_class_name)
|
35
40
|
end
|
36
41
|
|
37
42
|
# @return [String]
|
38
43
|
def default_source_class_name
|
39
|
-
entity_class.name
|
44
|
+
@default_source_class_name ||= entity_class.name
|
40
45
|
end
|
41
46
|
|
42
47
|
# @return [Set<Attribute>]
|
@@ -50,11 +55,6 @@ module Datamappify
|
|
50
55
|
@classified_attributes ||= Set.new(attributes).classify(&:provider_name)
|
51
56
|
end
|
52
57
|
|
53
|
-
# @return [Array<Attribute>]
|
54
|
-
def attributes_from_default_source
|
55
|
-
classified_attributes[default_provider_name].classify(&:source_class_name)[default_source_class_name]
|
56
|
-
end
|
57
|
-
|
58
58
|
private
|
59
59
|
|
60
60
|
# @return [Array<Symbol>]
|
@@ -78,24 +78,24 @@ module Datamappify
|
|
78
78
|
# @return [Array<Attribute>]
|
79
79
|
def default_attributes
|
80
80
|
@default_attributes ||= default_attribute_names.collect do |attribute|
|
81
|
-
Attribute.new(attribute, default_source_for(attribute))
|
81
|
+
Attribute.new(attribute, default_source_for(attribute), default_source_class)
|
82
82
|
end
|
83
83
|
end
|
84
84
|
|
85
85
|
# @return [Array<Attribute>]
|
86
86
|
def custom_attributes
|
87
87
|
@custom_attributes ||= custom_mapping.collect do |attribute, source|
|
88
|
-
|
88
|
+
map_custom_attribute(attribute, source)
|
89
89
|
end
|
90
90
|
end
|
91
91
|
|
92
92
|
# @param (see Data::Mapper::Attribute#initialize)
|
93
93
|
#
|
94
94
|
# @return [Attribute]
|
95
|
-
def
|
95
|
+
def map_custom_attribute(name, source)
|
96
96
|
@custom_attribute_names << name
|
97
97
|
|
98
|
-
Attribute.new(name, source)
|
98
|
+
Attribute.new(name, source, default_source_class)
|
99
99
|
end
|
100
100
|
|
101
101
|
# @param attribute [Symbol]
|
@@ -103,7 +103,7 @@ module Datamappify
|
|
103
103
|
#
|
104
104
|
# @return [String]
|
105
105
|
def default_source_for(attribute)
|
106
|
-
"#{default_provider_name}::#{
|
106
|
+
"#{default_provider_name}::#{default_source_class_name}##{attribute}"
|
107
107
|
end
|
108
108
|
end
|
109
109
|
end
|
@@ -4,11 +4,26 @@ module Datamappify
|
|
4
4
|
module ActiveRecord
|
5
5
|
extend CommonProvider
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
)
|
7
|
+
class << self
|
8
|
+
# @param source_class_name (see CommonProvider::ModuleMethods#find_or_build_record_class)
|
9
|
+
#
|
10
|
+
# @return [ActiveRecord::Base]
|
11
|
+
def build_record_class(source_class_name)
|
12
|
+
Datamappify::Data::Record::ActiveRecord.const_set(
|
13
|
+
source_class_name, Class.new(::ActiveRecord::Base)
|
14
|
+
)
|
15
|
+
end
|
16
|
+
|
17
|
+
# @return [void]
|
18
|
+
def build_record_association(attribute, default_source_class)
|
19
|
+
default_source_class.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
20
|
+
has_one :#{attribute.source_key}
|
21
|
+
CODE
|
22
|
+
|
23
|
+
attribute.source_class.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
24
|
+
belongs_to :#{default_source_class.model_name.element}
|
25
|
+
CODE
|
26
|
+
end
|
12
27
|
end
|
13
28
|
end
|
14
29
|
end
|
@@ -4,12 +4,31 @@ module Datamappify
|
|
4
4
|
module Sequel
|
5
5
|
extend CommonProvider
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
)
|
12
|
-
|
7
|
+
class << self
|
8
|
+
# @param source_class_name (see CommonProvider::ModuleMethods#find_or_build_record_class)
|
9
|
+
#
|
10
|
+
# @return [Sequel::Model]
|
11
|
+
def build_record_class(source_class_name)
|
12
|
+
Record::Sequel.const_set(
|
13
|
+
source_class_name, Class.new(::Sequel::Model(source_class_name.pluralize.underscore.to_sym))
|
14
|
+
).tap do |klass|
|
15
|
+
klass.raise_on_save_failure = true
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# @param attribute (see Record#build_association)
|
20
|
+
#
|
21
|
+
# @param default_source_class (see Record#build_association)
|
22
|
+
#
|
23
|
+
# @return [void]
|
24
|
+
def build_record_association(attribute, default_source_class)
|
25
|
+
default_source_class.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
26
|
+
one_to_one :#{attribute.source_key}
|
27
|
+
CODE
|
28
|
+
|
29
|
+
attribute.source_class.class_eval <<-CODE, __FILE__, __LINE__ + 1
|
30
|
+
one_to_one :#{default_source_class.table_name.to_s.singularize}
|
31
|
+
CODE
|
13
32
|
end
|
14
33
|
end
|
15
34
|
end
|
@@ -2,11 +2,24 @@ module Datamappify
|
|
2
2
|
module Data
|
3
3
|
# A convenient class for finding or building a data record
|
4
4
|
module Record
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
class << self
|
6
|
+
# @param provider_name [String]
|
7
|
+
#
|
8
|
+
# @param source_class_name (see CommonProvider::ModuleMethods#find_or_build_record_class)
|
9
|
+
#
|
10
|
+
# @return [Object]
|
11
|
+
def find_or_build(provider_name, source_class_name)
|
12
|
+
Provider.const_get(provider_name).find_or_build_record_class(source_class_name)
|
13
|
+
end
|
14
|
+
|
15
|
+
# @param attribute [Attribute]
|
16
|
+
#
|
17
|
+
# @param default_source_class [Class]
|
18
|
+
#
|
19
|
+
# @return [void]
|
20
|
+
def build_association(attribute, default_source_class)
|
21
|
+
Provider.const_get(attribute.provider_name).build_record_association(attribute, default_source_class)
|
22
|
+
end
|
10
23
|
end
|
11
24
|
end
|
12
25
|
end
|