datamappify 0.50.0 → 0.51.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|