data_broker 0.1.1 → 0.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7cce93d696af7204de9beab52b3bade4246b5ea5
4
- data.tar.gz: 46c4714f6c40eae60a6031a33071e88474dc3e57
3
+ metadata.gz: 81b7c541a17b1bb3a3325c508e1e689ddb6e79aa
4
+ data.tar.gz: d64dc71b65f7790ea9b10e34c18069f7030d4f8b
5
5
  SHA512:
6
- metadata.gz: 78ae6680a32a29baee7b0e77e3aa81225ec4c0aa731df41fdeafc254f82450b02d86a3bba3f1b03e42a6f21be2add36d8cffd9838ffaf83b3b183c0decbe06a8
7
- data.tar.gz: ca967a04b7452a6c7ad3db0e3ba799a7bf25d2d9304a824f8e8e10b4e2ffe27e8668656f3d8ea74908b3c4c70269a1daa10ce719824d77a4fb176a4857ad0ea7
6
+ metadata.gz: da87ff39f61766cea629984b2eb7848b00ad0c2566cdd15a5c90dbbc39b6de1fb023fcd529386c9929657e63fba2b861f58d3174c6d6d9756ea36dafb40251b9
7
+ data.tar.gz: 3b780b253eb5ee91cc69be3cfccb94f91204913f6968363dfb9a2bacd8002a8022284d76f79792a496851e98904e0c816637f5cb51c4fa64d6266c6e66018ba5
@@ -27,4 +27,5 @@ Gem::Specification.new do |spec|
27
27
  spec.add_development_dependency "rspec", "~> 3.0.0.beta1"
28
28
  spec.add_development_dependency "sqlite3", "~> 1.3"
29
29
  spec.add_development_dependency "database_cleaner", "~> 1.2"
30
+ spec.add_development_dependency "pry"
30
31
  end
@@ -16,10 +16,14 @@ module DataBroker
16
16
  end
17
17
 
18
18
  module ClassMethods
19
- attr_accessor :mapping, :relations
19
+ attr_accessor :mapping, :children, :parents
20
20
 
21
- def relations
22
- @relations || {}
21
+ def children
22
+ @children || {}
23
+ end
24
+
25
+ def parents
26
+ @parents || {}
23
27
  end
24
28
 
25
29
  [:record, :model].each do |attr|
@@ -34,86 +38,120 @@ module DataBroker
34
38
  end
35
39
 
36
40
  def all
37
- record_to_object(self.record.all)
41
+ records_to_objects(self.record.all)
38
42
  end
39
43
 
40
44
  def find(id)
41
- record = eager_record.find_by(:id => id)
42
- record.nil? ? nil : record_to_object(record, :eager_load => true)
45
+ record = self.eager_record.find_by(:id => id)
46
+ record.nil? ? nil : records_to_objects(record, :eager_load => true).first
43
47
  end
44
48
 
45
49
  def where(conds)
46
50
  conds = Hash[conds.map { |key, value| [self.mapping[key], value] }]
47
- record_to_object(
48
- eager_record.where(conds), :eager_load => true
49
- )
51
+ records_to_objects(self.eager_record.where(conds), :eager_load => true)
50
52
  end
51
53
 
52
54
  def save(model)
53
- record = self.record.find_by(:id => model.id) || self.record.new
55
+ record = self.eager_record.find_by(:id => model.id) || self.record.new
54
56
  attributes = Hash[self.mapping.map { |key, value| [value, model[key]] }]
55
57
  attributes.delete(:id)
56
58
  record.attributes = attributes
57
59
 
58
60
  record.save!
59
- record_to_object(record.reload)
61
+ records_to_objects(record.reload, :eager_load => true).first
60
62
  end
61
63
 
62
64
  def destroy(model)
63
65
  record = self.record.find_by(:id => model.id)
64
- record.nil? ? nil : record_to_object(record.destroy)
66
+ record.nil? ? nil : records_to_objects(record.destroy).first
65
67
  end
66
68
 
67
- def record_to_object(record, eager_load: false)
68
- if record.respond_to?(:each)
69
- record.compact.map { |rec| record_to_object(rec, :eager_load => eager_load) }
70
- else
69
+ def records_to_objects(records, eager_load: false)
70
+ records = [*records]
71
+ records.compact.map do |record|
71
72
  attributes = Hash[self.mapping.map { |key, value| [key, record[value]] }]
72
- self.model.new(attributes).tap do |model|
73
- eager_load_relations(model, record) if eager_load
73
+ self.model.new(attributes).tap do |obj|
74
+ load_parents!(obj, record) if eager_load
74
75
  end
76
+ end.tap do |recs|
77
+ load_children!(recs)
75
78
  end
76
79
  end
77
80
 
81
+ def eager_record
82
+ self.record.includes(parents.values)
83
+ end
84
+
78
85
  private
79
86
 
80
- def eager_load_relations(model, record)
81
- self.relations.each do |model_ref, record_ref|
82
- rec = record.send(record_ref)
83
- if rec
84
- ref_mapper = mapper_for(model_ref)
85
- ref = ref_mapper.record_to_object(rec)
86
- model.instance_variable_set(:"@#{model_ref}", ref)
87
+ def load_parents!(obj, record)
88
+ self.parents.each do |model_ref, record_ref|
89
+ parent_record = record.send(record_ref)
90
+ if parent_record
91
+ parent = load_parent(parent_record, model_ref)
92
+ obj.instance_variable_set(:"@#{model_ref}", parent)
93
+ end
94
+ end
95
+ end
96
+
97
+ def load_parent(parent_record, model)
98
+ @load_parent ||= {}
99
+ @load_parent[parent_record] ||= -> {
100
+ mapper = mapper_for(model)
101
+ mapper.records_to_objects(parent_record, :eager_load => false).first
102
+ }.call
103
+ end
104
+
105
+ def load_children!(records)
106
+ ids = records.map(&:id)
107
+ self.children.each do |model_ref, record_ref|
108
+ rec = record_for(model_ref)
109
+ rels = rec
110
+ .where(foreign_key => ids)
111
+ .pluck(foreign_key, :id)
112
+
113
+ records.each do |r|
114
+ r.instance_variable_set(
115
+ :"@#{model_ref.to_s.singularize}_ids",
116
+ rels.map { |id, vals| vals if id == r.id }.compact
117
+ )
87
118
  end
88
119
  end
89
120
  end
90
121
 
91
122
  def mapper_for(model_ref)
92
- "#{model_ref.to_s.singularize}_mapper".camelize.safe_constantize
123
+ @mapper_for ||= {}
124
+ @mapper_for[model_ref] ||= "#{model_ref.to_s.singularize}_mapper"
125
+ .camelize.safe_constantize
93
126
  end
94
127
 
95
- def inferred_basename
96
- self.to_s.underscore.sub(/_mapper$/, "").singularize.camelize
128
+ def record_for(model_ref)
129
+ @record_for ||= {}
130
+ @record_for[model_ref] ||= "#{model_ref.to_s.singularize}_record"
131
+ .camelize.safe_constantize
97
132
  end
98
133
 
99
- def inferred_model
100
- inferred_basename.safe_constantize
134
+ def foreign_key
135
+ @foreign_key ||= "#{inferred_basename.underscore}_id"
101
136
  end
102
137
 
103
- def infer(attr)
104
- if attr == :model
105
- inferred_model
106
- else
107
- "#{inferred_basename}#{attr.to_s.camelize}".safe_constantize
108
- end
138
+ def inferred_basename
139
+ @inferred_basename ||= self.to_s.underscore.sub(/_mapper$/, "")
140
+ .singularize.camelize
109
141
  end
110
142
 
111
- def eager_record
112
- self.record.includes(record_relations)
143
+ def inferred_model
144
+ @inferred_model ||= inferred_basename.safe_constantize
113
145
  end
114
146
 
115
- def record_relations
116
- self.relations.values
147
+ def infer(attr)
148
+ @infer ||= {}
149
+ @infer[attr] ||= if attr == :model
150
+ inferred_model
151
+ else
152
+ "#{inferred_basename}#{attr.to_s.camelize}"
153
+ .safe_constantize
154
+ end
117
155
  end
118
156
  end
119
157
  end
@@ -40,9 +40,12 @@ module DataBroker
40
40
 
41
41
  define_method(method) do
42
42
  ivar = "@#{method}"
43
- instance_variable_get(ivar) || instance_variable_set(
44
- ivar, constantize(mapper).where(via.to_sym => self.id)
45
- )
43
+ instance_variable_get(ivar) || -> {
44
+ instance_variable_set("@#{ids_method}", nil)
45
+ instance_variable_set(
46
+ ivar, constantize(mapper).where(via.to_sym => self.id)
47
+ )
48
+ }.call
46
49
  end
47
50
 
48
51
  define_method(ids_method) do
@@ -1,3 +1,3 @@
1
1
  module DataBroker
2
- VERSION = "0.1.1"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -43,7 +43,7 @@ class ParentMapper
43
43
  :id => :id
44
44
  }
45
45
 
46
- self.relations = {
46
+ self.children = {
47
47
  :children => :children
48
48
  }
49
49
  end
@@ -57,7 +57,7 @@ class ChildMapper
57
57
  :parent_id => :parent_id
58
58
  }
59
59
 
60
- self.relations = {
60
+ self.parents = {
61
61
  :parent => :parent
62
62
  }
63
63
  end
@@ -122,11 +122,13 @@ describe DataBroker::Mapper do
122
122
 
123
123
  it "eager loads belongs_to relations" do
124
124
  parent_id = parent_mapper.record.create.id
125
- id = mapper.record.create(:child_name => "Bobby", :parent_id => parent_id)
125
+ id = mapper.record.create(
126
+ :child_name => "Bobby", :parent_id => parent_id
127
+ ).id
126
128
  obj = parent_mapper.find(parent_id)
127
129
 
128
- child = obj.instance_variable_get(:@children).first
129
- expect(child).to eq(mapper.find(id))
130
+ ids = obj.instance_variable_get(:@child_ids)
131
+ expect(ids).to match_array([id])
130
132
  end
131
133
  end
132
134
 
@@ -176,11 +178,13 @@ describe DataBroker::Mapper do
176
178
 
177
179
  it "eager loads belongs_to relations" do
178
180
  parent_id = parent_mapper.record.create.id
179
- id = mapper.record.create(:child_name => "Bobby", :parent_id => parent_id)
181
+ id = mapper.record.create(
182
+ :child_name => "Bobby", :parent_id => parent_id
183
+ ).id
180
184
  obj = parent_mapper.where(:id => parent_id).first
181
185
 
182
- child = obj.instance_variable_get(:@children).first
183
- expect(child).to eq(mapper.find(id))
186
+ ids = obj.instance_variable_get(:@child_ids)
187
+ expect(ids).to match_array([id])
184
188
  end
185
189
  end
186
190
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: data_broker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Shane Emmons
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-01-10 00:00:00.000000000 Z
11
+ date: 2014-01-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: virtus
@@ -122,6 +122,20 @@ dependencies:
122
122
  - - "~>"
123
123
  - !ruby/object:Gem::Version
124
124
  version: '1.2'
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
125
139
  description: A simplified implementation of the data mapper pattern
126
140
  email:
127
141
  - oss@teamsnap.com