data_broker 0.1.1 → 0.2.0

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