datamappify 0.10.1 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +1 -0
  3. data/.travis.yml +2 -0
  4. data/CHANGELOG.md +11 -0
  5. data/README.md +55 -29
  6. data/datamappify.gemspec +4 -4
  7. data/lib/datamappify/data/errors.rb +3 -0
  8. data/lib/datamappify/data/provider/active_record/persistence.rb +31 -0
  9. data/lib/datamappify/data/provider/active_record.rb +16 -0
  10. data/lib/datamappify/data/provider/common/persistence.rb +57 -0
  11. data/lib/datamappify/data/provider/common/relational/persistence.rb +85 -0
  12. data/lib/datamappify/data/provider/common/relational/record/mapper.rb +24 -0
  13. data/lib/datamappify/data/provider/common/relational/record/writer.rb +67 -0
  14. data/lib/datamappify/data/provider/sequel/persistence.rb +31 -0
  15. data/lib/datamappify/data/provider/sequel.rb +18 -0
  16. data/lib/datamappify/data.rb +0 -1
  17. data/lib/datamappify/repository/attribute_source_data_class_builder.rb +16 -11
  18. data/lib/datamappify/repository/attributes_mapper.rb +17 -13
  19. data/lib/datamappify/repository/dsl.rb +9 -0
  20. data/lib/datamappify/repository/mapping_hash.rb +8 -0
  21. data/lib/datamappify/repository.rb +96 -4
  22. data/lib/datamappify/util.rb +13 -0
  23. data/lib/datamappify/version.rb +1 -1
  24. data/spec/entity_spec.rb +9 -8
  25. data/spec/repository/persistence_spec.rb +156 -56
  26. data/spec/repository_spec.rb +10 -33
  27. data/spec/spec_helper.rb +14 -8
  28. data/spec/support/entities/hero_user.rb +11 -0
  29. data/spec/support/entities/user.rb +5 -5
  30. data/spec/support/repositories/active_record/comment_repository.rb +6 -0
  31. data/spec/support/repositories/active_record/group_repository.rb +6 -0
  32. data/spec/support/repositories/active_record/role_repository.rb +6 -0
  33. data/spec/support/repositories/active_record/user_repository.rb +11 -0
  34. data/spec/support/repositories/hero_user_repository.rb +9 -0
  35. data/spec/support/repositories/sequel/comment_repository.rb +6 -0
  36. data/spec/support/repositories/sequel/group_repository.rb +6 -0
  37. data/spec/support/repositories/sequel/role_repository.rb +6 -0
  38. data/spec/support/repositories/sequel/user_repository.rb +11 -0
  39. data/spec/support/{active_record_tables.rb → tables/active_record.rb} +15 -9
  40. data/spec/support/tables/sequel.rb +76 -0
  41. metadata +64 -41
  42. data/lib/datamappify/data/base.rb +0 -7
  43. data/lib/datamappify/repository/persistence.rb +0 -137
  44. data/spec/support/repositories/comment_repository.rb +0 -7
  45. data/spec/support/repositories/group_repository.rb +0 -7
  46. data/spec/support/repositories/role_repository.rb +0 -7
  47. data/spec/support/repositories/user_repository.rb +0 -11
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ef8038f0a59981b26cab34b79e9358f9333d476d
4
- data.tar.gz: d39950946d1bafd3232ad8188242e1bb8e3b150f
3
+ metadata.gz: 657efe5662156ed237a7ff2a7abf02304ea48053
4
+ data.tar.gz: a5a1ab8c879d4948099679cdc12276970e80f8f3
5
5
  SHA512:
6
- metadata.gz: d41dc6a2da7f5fa2f72e1a6c3b9a7a6d6e3c68fe741a5845bd31f1081914343916a91b4f74b63c4f678b37e2b8dcdb2870830ad92d8cb31d9b738d3bccedffd4
7
- data.tar.gz: 14c092eda2c25e9d8b71853dd691ad7ffaf0b2fd63c3d6248654bfcc349c6e68b613d761b6732a9fcfa2b2a0edf923c8d28d1e17c91ea524c7079eab3e64b1e8
6
+ metadata.gz: 9d0fdeabfd8ba423d31bc70b7948c28419a10ae635e0189aa0e70be80db3c39a850532b2135c83c1df574204b0d7e48d84a67bd207e57ab7a3a150a7e0949869
7
+ data.tar.gz: b7ee5ed125413a9a5207355c018450d2440d738bc5fa9438a648c38848070eb708b28b5716b3f8f860ea21e4053a60cb803271323e430ccc9fcfa5bb3aa18476
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --colour --order random
data/.travis.yml CHANGED
@@ -2,5 +2,7 @@ language: ruby
2
2
  rvm:
3
3
  - 1.9.3
4
4
  - 2.0.0
5
+ env:
6
+ - COV=2
5
7
  script:
6
8
  - bundle exec rake --trace
data/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  ## master
2
2
 
3
+ ## 0.20.0 [2013-03-19]
4
+
5
+ - __Completely rewritten Repository__
6
+ - Repository now handles data construction from different ORM objects
7
+ - ActiveRecord has now been demoted to being a data provider, it is no longer tightly coupled with Repository, this means __we could have multiple data providers__!
8
+ - Repository is now much more robust
9
+ - As a result of robustness, it fixed an issue where updating an existing entity with new data records from mapped attributes will not persist the new data records correctly
10
+ - `#save` and `#destroy` now support accepting an array as their argument
11
+ - Added support for Sequel!
12
+ - Added support for mapping entity attributes to different ORMs!
13
+
3
14
  ## 0.10.1 [2013-03-16]
4
15
 
5
16
  - Fixed `#save` for creating new objects.
data/README.md CHANGED
@@ -1,24 +1,20 @@
1
- # Datamappify [![Gem Version](https://badge.fury.io/rb/datamappify.png)](http://badge.fury.io/rb/datamappify) [![Build Status](https://api.travis-ci.org/fredwu/datamappify.png)](http://travis-ci.org/fredwu/datamappify) [![Code Climate](https://codeclimate.com/github/fredwu/datamappify.png)](https://codeclimate.com/github/fredwu/datamappify)
1
+ # Datamappify [![Gem Version](https://badge.fury.io/rb/datamappify.png)](http://badge.fury.io/rb/datamappify) [![Build Status](https://api.travis-ci.org/fredwu/datamappify.png)](http://travis-ci.org/fredwu/datamappify) [![Coverage Status](https://coveralls.io/repos/fredwu/datamappify/badge.png)](https://coveralls.io/r/fredwu/datamappify) [![Code Climate](https://codeclimate.com/github/fredwu/datamappify.png)](https://codeclimate.com/github/fredwu/datamappify)
2
2
 
3
3
  Separate domain logic from data persistence, based on the [Repository Pattern](http://martinfowler.com/eaaCatalog/repository.html).
4
4
 
5
- __This library is current in Proof-of-Concept stage, do NOT use it for anything other than experimentation.__
5
+ Datamappify is NOT associated with the [Datamapper](https://github.com/datamapper/) project.
6
+
7
+ __Datamappify is current in Proof-of-Concept stage, do NOT use it for anything other than experimentation.__
6
8
 
7
9
  ## Overview
8
10
 
9
- Datamappify is a thin layer on top of ActiveRecord and [Virtus](https://github.com/solnic/virtus). The design goal is to utilise ActiveRecord but separate domain logic (behaviour) and data persistence.
11
+ Datamappify is a thin layer on top of [Virtus](https://github.com/solnic/virtus) and existing ORMs (ActiveRecord, etc). The design goal is to utilise the powerfulness of existing ORMs but separate domain logic (behaviour) from data persistence.
10
12
 
11
13
  Datamappify consists of three components:
12
14
 
13
- - Entity
14
- - Data
15
- - Repository
16
-
17
- __Entity__ is your model, it is responsible for mainly storing behaviour. Some structure (i.e. model relationships) is also stored here for convenience.
18
-
19
- __Data__ as the name suggests, holds your model data. It is an ActiveRecord object.
20
-
21
- __Repository__ is responsible for data retrieval and persistence, e.g. `find`, `save` and `destroy`, etc.
15
+ - __Entity__ is your model, it is responsible for mainly storing behaviour.
16
+ - __Data__ as the name suggests, holds your model data. It is an ActiveRecord object.
17
+ - __Repository__ is responsible for data retrieval and persistence, e.g. `find`, `save` and `destroy`, etc.
22
18
 
23
19
  ## Installation
24
20
 
@@ -38,15 +34,18 @@ Or install it yourself as:
38
34
 
39
35
  ### Entity
40
36
 
37
+ Entity uses [Virtus](https://github.com/solnic/virtus) DSL for defining attributes and [ActiveModel::Validations](http://api.rubyonrails.org/classes/ActiveModel/Validations.html) DSL for validations.
38
+
41
39
  ```ruby
42
40
  class User
43
41
  include Datamappify::Entity
44
42
 
45
- attribute :first_name, String
46
- attribute :last_name, String
47
- attribute :gender, String
48
- attribute :age, Integer
49
- attribute :passport, String
43
+ attribute :first_name, String
44
+ attribute :last_name, String
45
+ attribute :age, Integer
46
+ attribute :passport, String
47
+ attribute :driver_license, String
48
+ attribute :health_care, String
50
49
 
51
50
  validates :first_name, :presence => true,
52
51
  :length => { :minimum => 2 }
@@ -61,6 +60,8 @@ end
61
60
 
62
61
  ### Repository
63
62
 
63
+ Map entity attributes to DB columns - better yet, you can even map attributes to __different ORMs__!
64
+
64
65
  ```ruby
65
66
  class UserRepository
66
67
  include Datamappify::Repository
@@ -68,39 +69,63 @@ class UserRepository
68
69
  # specify the entity class
69
70
  for_entity User
70
71
 
72
+ # specify the default data provider for unmapped attributes
73
+ default_provider :ActiveRecord
74
+
71
75
  # specify any attributes that need to be mapped
72
76
  #
73
77
  # for example:
74
- # - 'gender' is mapped to the 'User' ActiveRecord class and its 'sex' attribute
75
- # - 'passport' is mapped to the 'UserPassport' ActiveRecord class and its 'number' attribute
76
- # - attributes not specified here are mapped automatically (in this case, 'User')
77
- map_attribute :gender, 'User#sex'
78
- map_attribute :passport, 'UserPassport#number'
78
+ # - 'last_name' is mapped to the 'User' ActiveRecord class and its 'surname' attribute
79
+ # - 'driver_license' is mapped to the 'UserDriverLicense' ActiveRecord class and its 'number' attribute
80
+ # - 'passport' is mapped to the 'UserPassport' Sequel class and its 'number' attribute
81
+ # - attributes not specified here are mapped automatically to 'ActiveRecord::User'
82
+ map_attribute :last_name, 'ActiveRecord::User#surname'
83
+ map_attribute :driver_license, 'ActiveRecord::UserDriverLicense#number'
84
+ map_attribute :passport, 'Sequel::UserPassport#number'
85
+ map_attribute :health_care, 'Sequel::UserHealthCare#number'
79
86
  end
80
-
81
- user_repository = UserRepository.instance
82
87
  ```
83
88
 
84
- #### Retrieving an entity
89
+ #### Retrieving entities
90
+
91
+ Pass in an id or an array of ids.
85
92
 
86
93
  ```ruby
87
- user = user_repository.find(1)
94
+ user = UserRepository.instance.find(1)
95
+ users = UserRepository.instance.find([1, 2, 3])
88
96
  ```
89
97
 
90
- #### Saving/updating an entity
98
+ #### Saving/updating entities
99
+
100
+ Pass in an entity or an array of entities.
101
+
102
+ There is also `save!` that raises `Datamappify::Data::EntityNotSaved`.
91
103
 
92
104
  ```ruby
93
- user_repository.save(user)
105
+ UserRepository.instance.save(user)
106
+ UserRepository.instance.save([user, user2, user3])
94
107
  ```
95
108
 
96
109
  #### Destroying an entity
97
110
 
111
+ Pass in an entity, an id, an array of entities or an array of ids.
112
+
113
+ There is also `destroy!` that raises `Datamappify::Data::EntityNotDestroyed`.
114
+
98
115
  Note that due to the attributes mapping, any data found in mapped ActiveRecord objects are not touched.
99
116
 
100
117
  ```ruby
101
- user_repository.destroy(user)
118
+ UserRepository.instance.destroy(1)
119
+ UserRepository.instance.destroy([1, 2, 3])
120
+ UserRepository.instance.destroy(user)
121
+ UserRepository.instance.destroy([user, user2, user3])
102
122
  ```
103
123
 
124
+ ## Supported ORMs
125
+
126
+ - ActiveRecord
127
+ - Sequel
128
+
104
129
  ## Changelog
105
130
 
106
131
  Refer to [CHANGELOG](CHANGELOG.md).
@@ -117,6 +142,7 @@ Refer to [CHANGELOG](CHANGELOG.md).
117
142
 
118
143
  - [Curator](https://github.com/braintree/curator)
119
144
  - [Edr](https://github.com/nulogy/edr)
145
+ - [Minimapper](https://github.com/joakimk/minimapper)
120
146
 
121
147
  ## Author
122
148
 
data/datamappify.gemspec CHANGED
@@ -20,16 +20,16 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_dependency "virtus", "~> 0.5"
22
22
  spec.add_dependency "activesupport", ">= 4.0.0.beta1", "< 5"
23
- spec.add_dependency "activerecord", ">= 4.0.0.beta1", "< 5"
24
23
 
25
24
  spec.add_development_dependency "bundler", "~> 1.3"
26
25
  spec.add_development_dependency "rake"
27
- spec.add_development_dependency "minitest"
28
- spec.add_development_dependency "minitest-colorize"
29
- spec.add_development_dependency "testrbl"
26
+ spec.add_development_dependency "rspec"
30
27
  spec.add_development_dependency "pry"
31
28
  spec.add_development_dependency "simplecov"
32
29
  spec.add_development_dependency "cane"
30
+ spec.add_development_dependency "coveralls"
33
31
  spec.add_development_dependency "sqlite3"
32
+ spec.add_development_dependency "sequel"
33
+ spec.add_development_dependency "activerecord", ">= 4.0.0.beta1", "< 5"
34
34
  spec.add_development_dependency "database_cleaner", ">= 1.0.0.RC1", "< 2"
35
35
  end
@@ -3,6 +3,9 @@ module Datamappify
3
3
  class Error < StandardError
4
4
  end
5
5
 
6
+ class MethodNotImplemented < NoMethodError
7
+ end
8
+
6
9
  class EntityInvalid < Error
7
10
  def initialize(entity)
8
11
  super entity.errors.full_messages.join(', ')
@@ -0,0 +1,31 @@
1
+ require 'datamappify/data/provider/common/relational/persistence'
2
+ require 'datamappify/data/provider/common/relational/record/mapper'
3
+ require 'datamappify/data/provider/common/relational/record/writer'
4
+
5
+ module Datamappify
6
+ module Data
7
+ module Provider
8
+ module ActiveRecord
9
+ class Persistence < Data::Provider::Common::Relational::Persistence
10
+ def destroy(ids)
11
+ data_class.destroy(ids)
12
+ end
13
+
14
+ def exists?(id)
15
+ data_class.exists?(id)
16
+ end
17
+
18
+ def transaction(&block)
19
+ data_class.transaction(&block)
20
+ end
21
+
22
+ private
23
+
24
+ def record_attributes_method
25
+ :attributes
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,16 @@
1
+ require 'datamappify/data/provider/active_record/persistence'
2
+
3
+ module Datamappify
4
+ module Data
5
+ module ActiveRecord
6
+ end
7
+
8
+ module Provider
9
+ module ActiveRecord
10
+ def self.build_data_class(data_class_name)
11
+ Datamappify::Data::ActiveRecord.const_set(data_class_name, Class.new(::ActiveRecord::Base))
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,57 @@
1
+ module Datamappify
2
+ module Data
3
+ module Provider
4
+ module Common
5
+ class Persistence
6
+ def initialize(provider_class_name, entities, data_class_name)
7
+ @provider_class_name = provider_class_name
8
+ @entities = entities
9
+ @data_class_name = data_class_name
10
+ end
11
+
12
+ def find(data_fields_mapping)
13
+ raise Data::MethodNotImplemented
14
+ end
15
+
16
+ def create(data_fields_mapping)
17
+ raise Data::MethodNotImplemented
18
+ end
19
+
20
+ def update(data_fields_mapping)
21
+ raise Data::MethodNotImplemented
22
+ end
23
+
24
+ def destroy(id_or_entity)
25
+ raise Data::MethodNotImplemented
26
+ end
27
+
28
+ def exists?(id)
29
+ raise Data::MethodNotImplemented
30
+ end
31
+
32
+ def transaction(&block)
33
+ raise Data::MethodNotImplemented
34
+ end
35
+
36
+ def method_missing(symbol, *args)
37
+ data_class.send symbol, *args
38
+ end
39
+
40
+ private
41
+
42
+ def data_class
43
+ "Datamappify::Data::#{@provider_class_name}::#{@data_class_name}".constantize
44
+ end
45
+
46
+ def entity_class_name
47
+ @entities[0].class.name
48
+ end
49
+
50
+ def is_entity_class?
51
+ @data_class_name == entity_class_name
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,85 @@
1
+ require 'datamappify/data/provider/common/persistence'
2
+
3
+ module Datamappify
4
+ module Data
5
+ module Provider
6
+ module Common
7
+ module Relational
8
+ class Persistence < Data::Provider::Common::Persistence
9
+ def find(data_fields_mapping)
10
+ records = find_records(data_fields_mapping)
11
+
12
+ entities_walker do |entity|
13
+ if record = find_record_for_entity(entity, records)
14
+ Common::Relational::RecordMapper.new(
15
+ entity, record.send(record_attributes_method)
16
+ ).map_attributes(data_fields_mapping)
17
+ end
18
+ end
19
+ end
20
+
21
+ def create(data_fields_mapping)
22
+ entities_walker do |entity|
23
+ if has_data_to_insert?(entity, data_fields_mapping)
24
+ Common::Relational::RecordWriter.new(
25
+ entity, data_class, key_field_name
26
+ ).insert_record(data_fields_mapping)
27
+ end
28
+ end
29
+ end
30
+
31
+ def update(data_fields_mapping)
32
+ records = find_records(data_fields_mapping)
33
+
34
+ entities_walker do |entity|
35
+ record_writer = Common::Relational::RecordWriter.new(entity, data_class, key_field_name)
36
+
37
+ if record = find_record_for_entity(entity, records)
38
+ record_writer.update_record(record, data_fields_mapping)
39
+ elsif has_data_to_insert?(entity, data_fields_mapping)
40
+ record_writer.insert_record(data_fields_mapping)
41
+ end
42
+ end
43
+ end
44
+
45
+ private
46
+
47
+ def find_record_for_entity(entity, records)
48
+ records.find { |r| r.send(key_field_name) == entity.id }
49
+ end
50
+
51
+ def find_records(data_fields_mapping)
52
+ data_class.select(
53
+ *field_names(data_fields_mapping)
54
+ ).where(
55
+ key_field_name => @entities.map(&:id)
56
+ )
57
+ end
58
+
59
+ def entities_walker
60
+ walker_method = is_entity_class? ? :keep_if : :each
61
+
62
+ @entities.send(walker_method) do |entity|
63
+ yield(entity)
64
+ end
65
+ end
66
+
67
+ def key_field_name
68
+ is_entity_class? ? :id : "#{entity_class_name.underscore}_id".to_sym
69
+ end
70
+
71
+ def field_names(data_fields_mapping)
72
+ (data_fields_mapping.field_names << key_field_name << :id).uniq
73
+ end
74
+
75
+ def has_data_to_insert?(entity, data_fields_mapping)
76
+ attribute_names = entity.attributes.keys & data_fields_mapping.attribute_names
77
+
78
+ attribute_names.any? && Util.attributes_filtered_by(entity, attribute_names).values.compact.any?
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,24 @@
1
+ module Datamappify
2
+ module Data
3
+ module Provider
4
+ module Common
5
+ module Relational
6
+ class RecordMapper
7
+ def initialize(entity, record_attributes)
8
+ @entity = entity
9
+ @record_attributes = record_attributes
10
+ end
11
+
12
+ def map_attributes(data_fields_mapping)
13
+ @record_attributes.each do |name, value|
14
+ return unless data_fields_mapping.has_key?(name.to_sym)
15
+
16
+ @entity.send(:"#{data_fields_mapping[name.to_sym]}=", value)
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,67 @@
1
+ module Datamappify
2
+ module Data
3
+ module Provider
4
+ module Common
5
+ module Relational
6
+ class RecordWriter
7
+ def initialize(entity, data_class, key_field_name)
8
+ @entity = entity
9
+ @data_class = data_class
10
+ @key_field_name = key_field_name
11
+ end
12
+
13
+ def insert_record(data_fields_mapping)
14
+ if is_foreign_record?
15
+ insert_foreign_record(data_fields_mapping)
16
+ else
17
+ new_record = insert_primary_record(data_fields_mapping)
18
+ update_entity_with_new_record_id(new_record.id)
19
+ end
20
+ end
21
+
22
+ def update_record(record, data_fields_mapping)
23
+ update_record_with_fields(record, data_fields_mapping)
24
+ end
25
+
26
+ private
27
+
28
+ def is_foreign_record?
29
+ @key_field_name != :id
30
+ end
31
+
32
+ def is_an_empty_primary_key?(attribute_name)
33
+ (attribute_name == :id) && @entity.attributes[attribute_name].nil?
34
+ end
35
+
36
+ def insert_foreign_record(data_fields_mapping)
37
+ new_record = @data_class.new
38
+ new_record.send "#{@key_field_name}=", @entity.id
39
+ update_record_with_fields(new_record, data_fields_mapping)
40
+ end
41
+
42
+ def insert_primary_record(data_fields_mapping)
43
+ update_record_with_fields(@data_class.new, data_fields_mapping)
44
+ end
45
+
46
+ def update_record_with_fields(record, data_fields_mapping)
47
+ data_fields_mapping.field_names.each do |field_name|
48
+ attribute_name = data_fields_mapping[field_name]
49
+
50
+ unless is_an_empty_primary_key?(attribute_name)
51
+ record.send "#{field_name}=", @entity.attributes[attribute_name]
52
+ end
53
+ end
54
+
55
+ record.save
56
+ record
57
+ end
58
+
59
+ def update_entity_with_new_record_id(id)
60
+ @entity.id = id
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,31 @@
1
+ require 'datamappify/data/provider/common/relational/persistence'
2
+ require 'datamappify/data/provider/common/relational/record/mapper'
3
+ require 'datamappify/data/provider/common/relational/record/writer'
4
+
5
+ module Datamappify
6
+ module Data
7
+ module Provider
8
+ module Sequel
9
+ class Persistence < Data::Provider::Common::Relational::Persistence
10
+ def destroy(ids)
11
+ data_class.where(:id => ids).destroy
12
+ end
13
+
14
+ def exists?(id)
15
+ data_class.where(:id => id).any?
16
+ end
17
+
18
+ def transaction(&block)
19
+ data_class.db.transaction(&block)
20
+ end
21
+
22
+ private
23
+
24
+ def record_attributes_method
25
+ :values
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,18 @@
1
+ require 'datamappify/data/provider/sequel/persistence'
2
+
3
+ module Datamappify
4
+ module Data
5
+ module Sequel
6
+ end
7
+
8
+ module Provider
9
+ module Sequel
10
+ def self.build_data_class(data_class_name)
11
+ Datamappify::Data::Sequel.const_set(
12
+ data_class_name, Class.new(::Sequel::Model(data_class_name.pluralize.underscore.to_sym))
13
+ )
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -1,5 +1,4 @@
1
1
  require 'datamappify/data/errors'
2
- require 'datamappify/data/base'
3
2
 
4
3
  module Datamappify
5
4
  module Data
@@ -1,22 +1,27 @@
1
1
  module Datamappify
2
2
  module Repository
3
3
  class AttributeSourceDataClassBuilder
4
- class << self
5
- def build(data_class_name, data_fields_mapping)
6
- @data_class_name = data_class_name
4
+ def initialize(provider_class_name, data_class_name)
5
+ @provider_class_name = provider_class_name
6
+ @data_class_name = data_class_name
7
+ end
8
+
9
+ def build(data_fields_mapping)
10
+ require "datamappify/data/provider/#{@provider_class_name.underscore}"
7
11
 
8
- build_data_class unless data_class_is_defined?
12
+ unless data_class_is_defined?
13
+ provider_module.build_data_class(@data_class_name)
9
14
  end
15
+ end
10
16
 
11
- private
17
+ private
12
18
 
13
- def build_data_class
14
- Data.const_set(@data_class_name, Class.new(Data::Base))
15
- end
19
+ def provider_module
20
+ @provider_module ||= "Datamappify::Data::Provider::#{@provider_class_name}".constantize
21
+ end
16
22
 
17
- def data_class_is_defined?
18
- Data.const_defined?(@data_class_name, false)
19
- end
23
+ def data_class_is_defined?
24
+ provider_module.const_defined?(@data_class_name, false)
20
25
  end
21
26
  end
22
27
  end
@@ -6,27 +6,29 @@ module Datamappify
6
6
  def initialize(repository)
7
7
  @repository = repository
8
8
 
9
- map_entity_attributes
9
+ map_non_custom_entity_attributes
10
+ map_custom_entity_attributes
10
11
  end
11
12
 
12
13
  def build_data_classes
13
- @repository.data_mapping.each do |data_class_name, data_fields_mapping|
14
- AttributeSourceDataClassBuilder.build(data_class_name, data_fields_mapping)
14
+ @repository.data_mapping.each do |provider_class_name, data_class_mapping|
15
+ data_class_mapping.each do |data_class_name, data_fields_mapping|
16
+ AttributeSourceDataClassBuilder.new(provider_class_name, data_class_name).build(data_fields_mapping)
17
+ end
15
18
  end
16
19
  end
17
20
 
18
21
  private
19
22
 
20
- def map_entity_attributes
21
- map_non_custom_entity_attributes
22
- map_custom_entity_attributes
23
- end
24
-
25
23
  def map_non_custom_entity_attributes
26
- @repository.data_mapping[@repository.entity_class.name] = {}
24
+ provider_name = @repository.default_provider_class_name
25
+ data_class_name = @repository.entity_class.name
26
+
27
+ @repository.data_mapping[provider_name] ||= {}
28
+ @repository.data_mapping[provider_name][data_class_name] ||= MappingHash.new
27
29
 
28
30
  non_custom_attributes.each do |attribute_name|
29
- @repository.data_mapping[@repository.entity_class.name][attribute_name] = attribute_name
31
+ @repository.data_mapping[provider_name][data_class_name][attribute_name] = attribute_name
30
32
  end
31
33
  end
32
34
 
@@ -41,10 +43,12 @@ module Datamappify
41
43
  end
42
44
 
43
45
  def map_custom_entity_attribute(attribute_name, source)
44
- data_class_name, data_field_name = source.split('#')
46
+ namespaced_data_class_name, data_field_name = source.split('#')
47
+ provider_name, data_class_name = namespaced_data_class_name.split('::')
45
48
 
46
- @repository.data_mapping[data_class_name] ||= {}
47
- @repository.data_mapping[data_class_name][data_field_name.to_sym] = attribute_name
49
+ @repository.data_mapping[provider_name] ||= {}
50
+ @repository.data_mapping[provider_name][data_class_name] ||= MappingHash.new
51
+ @repository.data_mapping[provider_name][data_class_name][data_field_name.to_sym] = attribute_name
48
52
  end
49
53
  end
50
54
  end