fire-model 0.0.10 → 0.0.11
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +133 -30
- data/VERSION +1 -1
- data/fire-model.gemspec +3 -3
- data/lib/fire-model.rb +4 -0
- data/lib/model/base.rb +20 -1
- data/lib/model/nested/base.rb +14 -0
- data/lib/model/nested/parent.rb +3 -1
- data/lib/model/nested/single.rb +2 -1
- data/lib/model/querying/querying.rb +2 -1
- data/spec/models/main_spec.rb +18 -3
- data/spec/models/nested_models_spec.rb +211 -186
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f20e6ee2e52181a1490b86b89ac6fd856ef625d
|
4
|
+
data.tar.gz: 47ed6a3f6a15e509dcd8a0be087b45fd2b0d10a0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b39771a4764b4ac5c23bf893092a1504c4db6813b119bb6868af7e4a25aa02abe276a89fec772157b787778a601e61391db08c61b425f1db9728c1d05cfb2507
|
7
|
+
data.tar.gz: dee861d2c31ed08b12b4ce2bc0a31bd37678c8e644e1be37c90c7b322cfd1a2564c88aecf7292852dc4bcbd752311cb01cecc5687ac0a6514889c94cc9b6de1f
|
data/README.md
CHANGED
@@ -15,11 +15,16 @@ end
|
|
15
15
|
|
16
16
|
Use query syntax
|
17
17
|
```ruby
|
18
|
-
LibraryBook.create(library: 'Shevchenko', floor: 1, row_number: 1, shelf: 10,
|
19
|
-
|
20
|
-
LibraryBook.create(library: 'Shevchenko', floor:
|
21
|
-
|
22
|
-
LibraryBook.create(library: '
|
18
|
+
LibraryBook.create(library: 'Shevchenko', floor: 1, row_number: 1, shelf: 10,
|
19
|
+
name: 'Kobzar', author: 'T.G. Shevchenko')
|
20
|
+
LibraryBook.create(library: 'Shevchenko', floor: 1, row_number: 1, shelf: 15,
|
21
|
+
name: 'Eneida', author: 'I. Kotlyrevskiy')
|
22
|
+
LibraryBook.create(library: 'Shevchenko', floor: 2, row_number: 15, shelf: 115,
|
23
|
+
name: 'Lord Of The Rings', author: ' J.R.R. Tolkien')
|
24
|
+
LibraryBook.create(library: 'Skovoroda', floor: 1, row_number: 25, shelf: 34,
|
25
|
+
name: 'Harry Potter', author: 'J.K. Rowling')
|
26
|
+
LibraryBook.create(library: 'Skovoroda', floor: 2, row_number: 12, shelf: 15,
|
27
|
+
name: 'Hobbit', author: ' J.R.R. Tolkien')
|
23
28
|
|
24
29
|
LibraryBook.all.map(&:name)
|
25
30
|
=> [ 'Kobzar', 'Eneida', 'Lord Of The Rings', 'Harry Potter', 'Hobbit' ]
|
@@ -118,6 +123,8 @@ larry == employee
|
|
118
123
|
employee.department = 'Research'
|
119
124
|
employee.save
|
120
125
|
=> true
|
126
|
+
|
127
|
+
google.reload
|
121
128
|
|
122
129
|
tim = apple.add_to_employees(
|
123
130
|
full_name: 'Tim Cook',
|
@@ -125,34 +132,130 @@ tim = apple.add_to_employees(
|
|
125
132
|
department: 'HQ'
|
126
133
|
)
|
127
134
|
|
128
|
-
Fire.
|
135
|
+
Fire.tree
|
129
136
|
=> {'Organization'=>
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
137
|
+
{'usa'=>
|
138
|
+
{'ca'=>
|
139
|
+
{'apple'=>
|
140
|
+
{'country'=>'USA',
|
141
|
+
'employees'=>
|
142
|
+
{'hq'=>
|
143
|
+
{'h543ka'=>
|
144
|
+
{'department'=>'HQ',
|
145
|
+
'full_name'=>'Tim Cook',
|
146
|
+
'id'=>'h543ka',
|
147
|
+
'position'=>'CEO'}}},
|
148
|
+
'name'=>'Apple',
|
149
|
+
'state'=>'CA'},
|
150
|
+
'google'=>
|
151
|
+
{'country'=>'USA',
|
152
|
+
'employees'=>
|
153
|
+
{'research'=>
|
154
|
+
{'d23h1a'=>
|
155
|
+
{'department'=>'Research',
|
156
|
+
'full_name'=>'Larry Page',
|
157
|
+
'id'=>'d23h1a',
|
158
|
+
'position'=>'CEO'}}},
|
159
|
+
'name'=>'Google',
|
160
|
+
'state'=>'CA'}}}}}
|
161
|
+
```
|
162
|
+
Single Nested Models
|
163
|
+
```ruby
|
164
|
+
class Car < Fire::Model
|
165
|
+
has_path_keys :manufacturer, :model, :car_class
|
166
|
+
end
|
154
167
|
|
168
|
+
class Engine < Fire::SingleNestedModel
|
169
|
+
nested_in Car
|
170
|
+
end
|
171
|
+
|
172
|
+
scirocco = Car.create(manufacturer: 'Volkswagen', model: 'Scirocco', car_class: 'Sport compact')
|
173
|
+
scirocco.add_to_engine(code: 'I4 turbo', power: '122 PS')
|
174
|
+
|
175
|
+
car = Car.create(manufacturer: 'Zaporozhets', model: 'ZAZ-965', car_class: 'Mini',
|
176
|
+
engine: { code: 'MeMZ-966' })
|
177
|
+
|
178
|
+
zaporozhets = Car.take(manufacturer: 'Zaporozhets', model: 'ZAZ-965', car_class: 'Mini', id: car.id)
|
179
|
+
expect(zaporozhets.nested_engine.code).to eq('MeMZ-966')
|
180
|
+
|
181
|
+
Fire.tree
|
182
|
+
=> {
|
183
|
+
'Car'=>
|
184
|
+
{'volkswagen'=>
|
185
|
+
{'scirocco'=>
|
186
|
+
{'sport-compact'=>
|
187
|
+
{'adqa21'=>
|
188
|
+
{'car_class'=>'Sport compact',
|
189
|
+
'engine'=>{'code'=>'I4 turbo', 'power'=>'122 PS'},
|
190
|
+
'id'=>'adqa21',
|
191
|
+
'manufacturer'=>'Volkswagen',
|
192
|
+
'model'=>'Scirocco'}}}},
|
193
|
+
'zaporozhets'=>
|
194
|
+
{'zaz-965'=>
|
195
|
+
{'mini'=>
|
196
|
+
{'23rtfw'=>
|
197
|
+
{'car_class'=>'Mini',
|
198
|
+
'engine'=>{'code'=>'MeMZ-966'},
|
199
|
+
'id'=>'23rtfw',
|
200
|
+
'manufacturer'=>'Zaporozhets',
|
201
|
+
'model'=>'ZAZ-965'}}}}}})
|
202
|
+
|
203
|
+
zap2 = Car.take(manufacturer: 'Zaporozhets', model: 'ZAZ-965', car_class: 'Mini', id: car.id)
|
204
|
+
zap2.nested_engine.update(code: 'MeMZ-555')
|
205
|
+
zaporozhets.nested_engine.reload.code
|
206
|
+
=> 'MeMZ-555'
|
207
|
+
```
|
155
208
|
|
209
|
+
Nested Models with Parent`s values
|
210
|
+
```ruby
|
211
|
+
class House < Fire::Model
|
212
|
+
has_path_keys :country, :city, :street
|
213
|
+
set_id_key(:house_number)
|
214
|
+
end
|
215
|
+
|
216
|
+
class Room < Fire::NestedModel
|
217
|
+
nested_in House, parent_values: true
|
218
|
+
set_id_key(:number)
|
219
|
+
has_path_keys :floor
|
220
|
+
end
|
221
|
+
|
222
|
+
house = House.create(country: 'Ukraine', city: 'Kyiv',
|
223
|
+
street: 'Shevchenko Ave.', house_number: '53101')
|
224
|
+
|
225
|
+
house.add_to_rooms(floor: 200, number: '1A')
|
226
|
+
house.add_to_rooms(floor: 150, number: '2A')
|
227
|
+
|
228
|
+
|
229
|
+
rooms = house.reload.nested_rooms
|
230
|
+
expect(rooms.map(&:number).sort).to eq(%w{ 1A 2A }.sort)
|
231
|
+
|
232
|
+
Fire.tree
|
233
|
+
=> {'House'=>
|
234
|
+
{'ukraine'=>
|
235
|
+
{'kyiv'=>
|
236
|
+
{'shevchenko-ave'=>
|
237
|
+
{'53101'=>
|
238
|
+
{'city'=>'Kyiv',
|
239
|
+
'country'=>'Ukraine',
|
240
|
+
'house_number'=>'53101',
|
241
|
+
'rooms'=>
|
242
|
+
{'150_'=>
|
243
|
+
{'2a'=>
|
244
|
+
{'city'=>'Kyiv',
|
245
|
+
'country'=>'Ukraine',
|
246
|
+
'floor'=>150,
|
247
|
+
'number'=>'2A',
|
248
|
+
'house_number'=>'53101',
|
249
|
+
'street'=>'Shevchenko Ave.'}},
|
250
|
+
'200_'=>
|
251
|
+
{'1a'=>
|
252
|
+
{'city'=>'Kyiv',
|
253
|
+
'country'=>'Ukraine',
|
254
|
+
'floor'=>200,
|
255
|
+
'number'=>'1A',
|
256
|
+
'house_number'=>'53101',
|
257
|
+
'street'=>'Shevchenko Ave.'}}},
|
258
|
+
'street'=>'Shevchenko Ave.'}}}}}})
|
156
259
|
```
|
157
260
|
|
158
261
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.11
|
data/fire-model.gemspec
CHANGED
@@ -2,16 +2,16 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: fire-model 0.0.
|
5
|
+
# stub: fire-model 0.0.11 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "fire-model"
|
9
|
-
s.version = "0.0.
|
9
|
+
s.version = "0.0.11"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["Vitaly Tarasenko"]
|
14
|
-
s.date = "2015-06-
|
14
|
+
s.date = "2015-06-21"
|
15
15
|
s.description = "You can define your Firebase models, set collection names, CRUD your data. "
|
16
16
|
s.email = "vetal.tarasenko@gmail.com"
|
17
17
|
s.extra_rdoc_files = [
|
data/lib/fire-model.rb
CHANGED
data/lib/model/base.rb
CHANGED
@@ -54,6 +54,18 @@ module Fire
|
|
54
54
|
([ collection_name ] + path_values) * LEVEL_SEPARATOR
|
55
55
|
end
|
56
56
|
|
57
|
+
def reload
|
58
|
+
loaded_data = self.class.take(path_data).data
|
59
|
+
@table = loaded_data
|
60
|
+
@cache = {}
|
61
|
+
self
|
62
|
+
end
|
63
|
+
|
64
|
+
def update(attrs)
|
65
|
+
@table.merge!(attrs)
|
66
|
+
save
|
67
|
+
end
|
68
|
+
|
57
69
|
# Data Methods
|
58
70
|
|
59
71
|
def path_values
|
@@ -102,6 +114,11 @@ module Fire
|
|
102
114
|
data
|
103
115
|
end
|
104
116
|
|
117
|
+
def cache(key, &value)
|
118
|
+
@cache ||= {}
|
119
|
+
@cache[key] ||= value.call
|
120
|
+
end
|
121
|
+
|
105
122
|
class << self
|
106
123
|
|
107
124
|
# Klass Setters
|
@@ -196,10 +213,12 @@ module Fire
|
|
196
213
|
end
|
197
214
|
|
198
215
|
require_relative './querying/querying'
|
216
|
+
include Querying
|
217
|
+
|
199
218
|
require_relative './nested/base'
|
200
219
|
require_relative './nested/single'
|
201
220
|
require_relative './nested/parent'
|
202
|
-
|
221
|
+
|
203
222
|
include NestedModel::Parent
|
204
223
|
end
|
205
224
|
end
|
data/lib/model/nested/base.rb
CHANGED
@@ -55,6 +55,14 @@ module Fire
|
|
55
55
|
}
|
56
56
|
end
|
57
57
|
|
58
|
+
def query(params={}, &filter_condition)
|
59
|
+
raise QueryingNotSupportedError.new
|
60
|
+
end
|
61
|
+
|
62
|
+
def all
|
63
|
+
query
|
64
|
+
end
|
65
|
+
|
58
66
|
protected
|
59
67
|
|
60
68
|
def default_folder_name
|
@@ -89,6 +97,12 @@ module Fire
|
|
89
97
|
end
|
90
98
|
end
|
91
99
|
|
100
|
+
class QueryingNotSupportedError < FireModelError
|
101
|
+
def initialize
|
102
|
+
super("Nested Models do not support querying")
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
92
106
|
end
|
93
107
|
|
94
108
|
end
|
data/lib/model/nested/parent.rb
CHANGED
data/lib/model/nested/single.rb
CHANGED
@@ -12,7 +12,8 @@ module Fire
|
|
12
12
|
response = connection.get(full_path).body
|
13
13
|
return [] if response.nil?
|
14
14
|
|
15
|
-
|
15
|
+
needed_levels = (all_path_keys - direct_keys - default_path_keys).count
|
16
|
+
rows = down_levels(response, needed_levels)
|
16
17
|
|
17
18
|
filter_result(rows, filter_opts(params, direct_keys), filter_condition)
|
18
19
|
end
|
data/spec/models/main_spec.rb
CHANGED
@@ -146,7 +146,7 @@ describe 'Fire Models' do
|
|
146
146
|
has_path_keys(:library, :floor, :row_number, :shelf)
|
147
147
|
end
|
148
148
|
|
149
|
-
LibraryBook.create(library: 'Shevchenko', floor: 1, row_number: 1, shelf: 10, name: 'Kobzar', author: 'T.G. Shevchenko')
|
149
|
+
book = LibraryBook.create(library: 'Shevchenko', floor: 1, row_number: 1, shelf: 10, name: 'Kobzar', author: 'T.G. Shevchenko')
|
150
150
|
LibraryBook.create(library: 'Shevchenko', floor: 1, row_number: 1, shelf: 15, name: 'Eneida', author: 'I. Kotlyrevskiy')
|
151
151
|
LibraryBook.create(library: 'Shevchenko', floor: 2, row_number: 15, shelf: 115, name: 'Lord Of The Rings', author: ' J.R.R. Tolkien')
|
152
152
|
LibraryBook.create(library: 'Skovoroda', floor: 1, row_number: 25, shelf: 34, name: 'Harry Potter', author: 'J.K. Rowling')
|
@@ -172,6 +172,12 @@ describe 'Fire Models' do
|
|
172
172
|
|
173
173
|
# Query by math condition
|
174
174
|
expect(LibraryBook.query{|m| m.row_number % 5 == 0 }.map(&:name)).to eq([ 'Lord Of The Rings', 'Harry Potter' ])
|
175
|
+
|
176
|
+
# Query by full path
|
177
|
+
expect(LibraryBook.query(library: 'Shevchenko', floor: 1, row_number: 1, shelf: 10).map(&:name)).to eq([ 'Kobzar' ])
|
178
|
+
|
179
|
+
# Take by full path + ID
|
180
|
+
expect(LibraryBook.take(library: 'Shevchenko', floor: 1, row_number: 1, shelf: 10, id: book.id).name).to eq('Kobzar')
|
175
181
|
end
|
176
182
|
|
177
183
|
end
|
@@ -184,6 +190,7 @@ describe 'Fire Models' do
|
|
184
190
|
has_path_keys(:x, :y)
|
185
191
|
end
|
186
192
|
|
193
|
+
# Creating
|
187
194
|
p1 = Point.create(x: 1, y: 1, value: 1)
|
188
195
|
p2 = Point.create(x: 1, y: 2, value: 2)
|
189
196
|
p3 = Point.create(x: 2, y: 1, value: 3)
|
@@ -191,23 +198,31 @@ describe 'Fire Models' do
|
|
191
198
|
|
192
199
|
expect(Point.all.map(&:value).sort).to eq([ 1, 2, 3, 4 ].sort)
|
193
200
|
|
201
|
+
# ID generation
|
194
202
|
expect(p1.id).to be
|
195
203
|
|
204
|
+
# Updating
|
196
205
|
p1.value = 5
|
197
206
|
expect(p1.path_changed?).to be_falsey
|
198
207
|
p1.save
|
199
208
|
|
209
|
+
|
200
210
|
expect(Point.all.map(&:value).sort).to eq([ 5, 2, 3, 4 ].sort)
|
201
211
|
|
202
212
|
reloaded_point = Point.take(x: p2.x, y: p2.y, id: p2.id)
|
203
|
-
reloaded_point.value
|
213
|
+
reloaded_point.update(value: 6)
|
204
214
|
|
205
215
|
expect(reloaded_point.path_changed?).to be_falsey
|
206
216
|
|
207
217
|
reloaded_point.save
|
208
|
-
|
209
218
|
expect(Point.all.map(&:value).sort).to eq([ 5, 6, 3, 4 ].sort)
|
210
219
|
|
220
|
+
# Reloading
|
221
|
+
expect(p2.value).to eq(2)
|
222
|
+
p2.reload
|
223
|
+
expect(p2.value).to eq(6)
|
224
|
+
|
225
|
+
# Deletion
|
211
226
|
p1.delete
|
212
227
|
|
213
228
|
expect(Point.all.map(&:value).sort).to eq([ 6, 3, 4].sort)
|
@@ -2,210 +2,223 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe 'Nested Models' do
|
4
4
|
|
5
|
-
|
6
|
-
Fire.drop!
|
7
|
-
end
|
8
|
-
|
9
|
-
after :each do
|
10
|
-
Fire.drop!
|
11
|
-
end
|
5
|
+
context 'With Firebase Connection' do
|
12
6
|
|
13
|
-
|
14
|
-
|
15
|
-
class Organization < Fire::Model
|
16
|
-
has_path_keys :country, :state
|
17
|
-
set_id_key(:name)
|
7
|
+
before :each do
|
8
|
+
Fire.drop!
|
18
9
|
end
|
19
10
|
|
20
|
-
|
11
|
+
after :each do
|
12
|
+
Fire.drop!
|
13
|
+
end
|
21
14
|
|
22
|
-
|
23
|
-
|
24
|
-
has_path_keys :department
|
15
|
+
def current_data
|
16
|
+
Fire.tree
|
25
17
|
end
|
26
18
|
|
27
|
-
|
28
|
-
|
29
|
-
google = Organization.create(name: 'Google', country: 'USA', state: 'CA')
|
30
|
-
apple = Organization.create(name: 'Apple', country: 'USA', state: 'CA')
|
31
|
-
|
32
|
-
expect(current_data).to eq(
|
33
|
-
{'Organization'=>
|
34
|
-
{'usa'=>
|
35
|
-
{'ca'=>
|
36
|
-
{'apple'=>{'country'=>'USA', 'name'=>'Apple', 'state'=>'CA'},
|
37
|
-
'google'=>{'country'=>'USA', 'name'=>'Google', 'state'=>'CA'}}}}})
|
38
|
-
|
39
|
-
larry = Employee.create(name: 'Google', country: 'USA', state: 'CA',
|
40
|
-
department: 'HQ', full_name: 'Larry Page', position: 'CEO')
|
41
|
-
|
42
|
-
expect(current_data).to eq(
|
43
|
-
{'Organization'=>
|
44
|
-
{'usa'=>
|
45
|
-
{'ca'=>
|
46
|
-
{'apple'=>{'country'=>'USA', 'name'=>'Apple', 'state'=>'CA'},
|
47
|
-
'google'=>{
|
48
|
-
'country'=>'USA', 'name'=>'Google', 'state'=>'CA', 'employees' => {
|
49
|
-
'hq' => {
|
50
|
-
larry.id => {
|
51
|
-
'id' => larry.id,
|
52
|
-
'full_name' => 'Larry Page',
|
53
|
-
'position' => 'CEO',
|
54
|
-
'department' => 'HQ',
|
55
|
-
}}}}}}}})
|
56
|
-
|
57
|
-
google = Organization.query(name: 'Google').first
|
58
|
-
google.nested_employees
|
59
|
-
|
60
|
-
employee = google.nested_employees.first
|
61
|
-
expect(larry).to eq(employee)
|
62
|
-
|
63
|
-
employee.department = 'Research'
|
64
|
-
employee.save
|
65
|
-
|
66
|
-
expect(current_data).to eq(
|
67
|
-
{'Organization'=>
|
68
|
-
{'usa'=>
|
69
|
-
{'ca'=>
|
70
|
-
{'apple'=>{'country'=>'USA', 'name'=>'Apple', 'state'=>'CA'},
|
71
|
-
'google'=>{
|
72
|
-
'country'=>'USA', 'name'=>'Google', 'state'=>'CA', 'employees' => {
|
73
|
-
'research' => {
|
74
|
-
larry.id => {
|
75
|
-
'id' => larry.id,
|
76
|
-
'full_name' => 'Larry Page',
|
77
|
-
'position' => 'CEO',
|
78
|
-
'department' => 'Research',
|
79
|
-
}}}}}}}})
|
80
|
-
|
81
|
-
apple = Organization.query(name: 'Apple').first
|
82
|
-
tim = apple.add_to_employees(
|
83
|
-
full_name: 'Tim Cook',
|
84
|
-
position: 'CEO',
|
85
|
-
department: 'HQ'
|
86
|
-
)
|
87
|
-
|
88
|
-
expect(current_data).to eq(
|
89
|
-
{'Organization'=>
|
90
|
-
{'usa'=>
|
91
|
-
{'ca'=>
|
92
|
-
{'apple'=>
|
93
|
-
{'country'=>'USA',
|
94
|
-
'employees'=>
|
95
|
-
{'hq'=>
|
96
|
-
{tim.id=>
|
97
|
-
{'department'=>'HQ',
|
98
|
-
'full_name'=>'Tim Cook',
|
99
|
-
'id'=>tim.id,
|
100
|
-
'position'=>'CEO'}}},
|
101
|
-
'name'=>'Apple',
|
102
|
-
'state'=>'CA'},
|
103
|
-
'google'=>
|
104
|
-
{'country'=>'USA',
|
105
|
-
'employees'=>
|
106
|
-
{'research'=>
|
107
|
-
{larry.id=>
|
108
|
-
{'department'=>'Research',
|
109
|
-
'full_name'=>'Larry Page',
|
110
|
-
'id'=>larry.id,
|
111
|
-
'position'=>'CEO'}}},
|
112
|
-
'name'=>'Google',
|
113
|
-
'state'=>'CA'}}}}}
|
114
|
-
)
|
115
|
-
end
|
19
|
+
it 'should declare nested models' do
|
116
20
|
|
117
|
-
|
21
|
+
class Organization < Fire::Model
|
22
|
+
has_path_keys :country, :state
|
23
|
+
set_id_key(:name)
|
24
|
+
end
|
118
25
|
|
119
|
-
|
26
|
+
expect(Organization.nested_models).to be_empty
|
120
27
|
|
121
|
-
class
|
122
|
-
|
28
|
+
class Employee < Fire::NestedModel
|
29
|
+
nested_in Organization
|
30
|
+
has_path_keys :department
|
123
31
|
end
|
124
32
|
|
125
|
-
|
126
|
-
|
127
|
-
|
33
|
+
expect(Organization.nested_models).to eq([ Employee ])
|
34
|
+
|
35
|
+
google = Organization.create(name: 'Google', country: 'USA', state: 'CA')
|
36
|
+
apple = Organization.create(name: 'Apple', country: 'USA', state: 'CA')
|
128
37
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
38
|
+
expect(current_data).to eq(
|
39
|
+
{'Organization'=>
|
40
|
+
{'usa'=>
|
41
|
+
{'ca'=>
|
42
|
+
{'apple'=>{'country'=>'USA', 'name'=>'Apple', 'state'=>'CA'},
|
43
|
+
'google'=>{'country'=>'USA', 'name'=>'Google', 'state'=>'CA'}}}}})
|
44
|
+
|
45
|
+
larry = Employee.create(name: 'Google', country: 'USA', state: 'CA',
|
46
|
+
department: 'HQ', full_name: 'Larry Page', position: 'CEO')
|
47
|
+
|
48
|
+
expect(current_data).to eq(
|
49
|
+
{'Organization'=>
|
50
|
+
{'usa'=>
|
51
|
+
{'ca'=>
|
52
|
+
{'apple'=>{'country'=>'USA', 'name'=>'Apple', 'state'=>'CA'},
|
53
|
+
'google'=>{
|
54
|
+
'country'=>'USA', 'name'=>'Google', 'state'=>'CA', 'employees' => {
|
55
|
+
'hq' => {
|
56
|
+
larry.id => {
|
57
|
+
'id' => larry.id,
|
58
|
+
'full_name' => 'Larry Page',
|
59
|
+
'position' => 'CEO',
|
60
|
+
'department' => 'HQ',
|
61
|
+
}}}}}}}})
|
62
|
+
|
63
|
+
|
64
|
+
employee = google.reload.nested_employees.first
|
65
|
+
expect(larry).to eq(employee)
|
66
|
+
|
67
|
+
employee.update(department: 'Research')
|
68
|
+
|
69
|
+
expect(current_data).to eq(
|
70
|
+
{'Organization'=>
|
71
|
+
{'usa'=>
|
72
|
+
{'ca'=>
|
73
|
+
{'apple'=>{'country'=>'USA', 'name'=>'Apple', 'state'=>'CA'},
|
74
|
+
'google'=>{
|
75
|
+
'country'=>'USA', 'name'=>'Google', 'state'=>'CA', 'employees' => {
|
76
|
+
'research' => {
|
77
|
+
larry.id => {
|
78
|
+
'id' => larry.id,
|
79
|
+
'full_name' => 'Larry Page',
|
80
|
+
'position' => 'CEO',
|
81
|
+
'department' => 'Research',
|
82
|
+
}}}}}}}})
|
83
|
+
|
84
|
+
tim = apple.add_to_employees(
|
85
|
+
full_name: 'Tim Cook',
|
86
|
+
position: 'CEO',
|
87
|
+
department: 'HQ'
|
88
|
+
)
|
89
|
+
|
90
|
+
expect(current_data).to eq(
|
91
|
+
{'Organization'=>
|
92
|
+
{'usa'=>
|
93
|
+
{'ca'=>
|
94
|
+
{'apple'=>
|
95
|
+
{'country'=>'USA',
|
96
|
+
'employees'=>
|
97
|
+
{'hq'=>
|
98
|
+
{tim.id=>
|
99
|
+
{'department'=>'HQ',
|
100
|
+
'full_name'=>'Tim Cook',
|
101
|
+
'id'=>tim.id,
|
102
|
+
'position'=>'CEO'}}},
|
103
|
+
'name'=>'Apple',
|
104
|
+
'state'=>'CA'},
|
105
|
+
'google'=>
|
106
|
+
{'country'=>'USA',
|
107
|
+
'employees'=>
|
108
|
+
{'research'=>
|
109
|
+
{larry.id=>
|
110
|
+
{'department'=>'Research',
|
111
|
+
'full_name'=>'Larry Page',
|
112
|
+
'id'=>larry.id,
|
113
|
+
'position'=>'CEO'}}},
|
114
|
+
'name'=>'Google',
|
115
|
+
'state'=>'CA'}}}}}
|
116
|
+
)
|
157
117
|
end
|
158
118
|
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
set_id_key(:house_number)
|
163
|
-
end
|
119
|
+
context 'Nested Models Types' do
|
120
|
+
|
121
|
+
it 'should declare single nested models' do
|
164
122
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
123
|
+
class Car < Fire::Model
|
124
|
+
has_path_keys :manufacturer, :model, :car_class
|
125
|
+
end
|
126
|
+
|
127
|
+
class Engine < Fire::SingleNestedModel
|
128
|
+
nested_in Car
|
129
|
+
end
|
130
|
+
|
131
|
+
scirocco = Car.create(manufacturer: 'Volkswagen', model: 'Scirocco', car_class: 'Sport compact')
|
132
|
+
scirocco.add_to_engine(code: 'I4 turbo', power: '122 PS')
|
133
|
+
|
134
|
+
car = Car.create(manufacturer: 'Zaporozhets', model: 'ZAZ-965', car_class: 'Mini', engine: { code: 'MeMZ-966' })
|
135
|
+
|
136
|
+
zaporozhets = Car.take(manufacturer: 'Zaporozhets', model: 'ZAZ-965', car_class: 'Mini', id: car.id)
|
137
|
+
expect(zaporozhets.nested_engine.code).to eq('MeMZ-966')
|
138
|
+
|
139
|
+
expect(current_data).to eq({
|
140
|
+
'Car'=>
|
141
|
+
{'volkswagen'=>
|
142
|
+
{'scirocco'=>
|
143
|
+
{'sport-compact'=>
|
144
|
+
{scirocco.id=>
|
145
|
+
{'car_class'=>'Sport compact',
|
146
|
+
'engine'=>{'code'=>'I4 turbo', 'power'=>'122 PS'},
|
147
|
+
'id'=>scirocco.id,
|
148
|
+
'manufacturer'=>'Volkswagen',
|
149
|
+
'model'=>'Scirocco'}}}},
|
150
|
+
'zaporozhets'=>
|
151
|
+
{'zaz-965'=>
|
152
|
+
{'mini'=>
|
153
|
+
{zaporozhets.id=>
|
154
|
+
{'car_class'=>'Mini',
|
155
|
+
'engine'=>{'code'=>'MeMZ-966'},
|
156
|
+
'id'=>zaporozhets.id,
|
157
|
+
'manufacturer'=>'Zaporozhets',
|
158
|
+
'model'=>'ZAZ-965'}}}}}})
|
159
|
+
|
160
|
+
# nested association caching
|
161
|
+
zaporozhets.nested_engine.code = 'MeMZ-777'
|
162
|
+
expect(zaporozhets.nested_engine.code).to eq('MeMZ-777')
|
163
|
+
expect(zaporozhets.reload.nested_engine.code).to eq('MeMZ-966')
|
164
|
+
|
165
|
+
# nested association saving
|
166
|
+
zap2 = Car.take(manufacturer: 'Zaporozhets', model: 'ZAZ-965', car_class: 'Mini', id: car.id)
|
167
|
+
zap2.nested_engine.update(code: 'MeMZ-555')
|
168
|
+
expect(zaporozhets.nested_engine.reload.code).to eq('MeMZ-555')
|
169
169
|
end
|
170
170
|
|
171
|
-
|
172
|
-
|
173
|
-
|
171
|
+
it 'should allow to declare nested models with all *parent values* duplicated' do
|
172
|
+
class House < Fire::Model
|
173
|
+
has_path_keys :country, :city, :street
|
174
|
+
set_id_key(:house_number)
|
175
|
+
end
|
176
|
+
|
177
|
+
class Room < Fire::NestedModel
|
178
|
+
nested_in House, parent_values: true
|
179
|
+
set_id_key(:number)
|
180
|
+
has_path_keys :floor
|
181
|
+
end
|
174
182
|
|
175
|
-
|
176
|
-
|
177
|
-
|
183
|
+
house = House.create(country: 'Ukraine', city: 'Kyiv', street: 'Shevchenko Ave.', house_number: '53101')
|
184
|
+
house.add_to_rooms(floor: 200, number: '1A')
|
185
|
+
house.add_to_rooms(floor: 150, number: '2A')
|
186
|
+
|
187
|
+
|
188
|
+
rooms = house.reload.nested_rooms
|
189
|
+
expect(rooms.map(&:number).sort).to eq(%w{ 1A 2A }.sort)
|
190
|
+
|
191
|
+
expect(current_data).to eq(
|
192
|
+
{'House'=>
|
193
|
+
{'ukraine'=>
|
194
|
+
{'kyiv'=>
|
195
|
+
{'shevchenko-ave'=>
|
196
|
+
{'53101'=>
|
197
|
+
{'city'=>'Kyiv',
|
198
|
+
'country'=>'Ukraine',
|
199
|
+
'house_number'=>'53101',
|
200
|
+
'rooms'=>
|
201
|
+
{'150_'=>
|
202
|
+
{'2a'=>
|
203
|
+
{'city'=>'Kyiv',
|
204
|
+
'country'=>'Ukraine',
|
205
|
+
'floor'=>150,
|
206
|
+
'number'=>'2A',
|
207
|
+
'house_number'=>'53101',
|
208
|
+
'street'=>'Shevchenko Ave.'}},
|
209
|
+
'200_'=>
|
210
|
+
{'1a'=>
|
211
|
+
{'city'=>'Kyiv',
|
212
|
+
'country'=>'Ukraine',
|
213
|
+
'floor'=>200,
|
214
|
+
'number'=>'1A',
|
215
|
+
'house_number'=>'53101',
|
216
|
+
'street'=>'Shevchenko Ave.'}}},
|
217
|
+
'street'=>'Shevchenko Ave.'}}}}}})
|
178
218
|
|
179
|
-
|
180
|
-
{'House'=>
|
181
|
-
{'ukraine'=>
|
182
|
-
{'kyiv'=>
|
183
|
-
{'shevchenko-ave'=>
|
184
|
-
{'53101'=>
|
185
|
-
{'city'=>'Kyiv',
|
186
|
-
'country'=>'Ukraine',
|
187
|
-
'house_number'=>'53101',
|
188
|
-
'rooms'=>
|
189
|
-
{'150_'=>
|
190
|
-
{'2a'=>
|
191
|
-
{'city'=>'Kyiv',
|
192
|
-
'country'=>'Ukraine',
|
193
|
-
'floor'=>150,
|
194
|
-
'number'=>'2A',
|
195
|
-
'house_number'=>'53101',
|
196
|
-
'street'=>'Shevchenko Ave.'}},
|
197
|
-
'200_'=>
|
198
|
-
{'1a'=>
|
199
|
-
{'city'=>'Kyiv',
|
200
|
-
'country'=>'Ukraine',
|
201
|
-
'floor'=>200,
|
202
|
-
'number'=>'1A',
|
203
|
-
'house_number'=>'53101',
|
204
|
-
'street'=>'Shevchenko Ave.'}}},
|
205
|
-
'street'=>'Shevchenko Ave.'}}}}}})
|
219
|
+
end
|
206
220
|
|
207
221
|
end
|
208
|
-
|
209
222
|
end
|
210
223
|
|
211
224
|
context 'Restrictions' do
|
@@ -262,10 +275,22 @@ describe 'Nested Models' do
|
|
262
275
|
end
|
263
276
|
}).to raise_error(Fire::SingleNestedModel::PathKeysNotSupported)
|
264
277
|
end
|
265
|
-
end
|
266
278
|
|
267
|
-
|
268
|
-
|
279
|
+
it 'should now allow to query by Nested Models' do
|
280
|
+
class Earth < Fire::Model
|
281
|
+
|
282
|
+
end
|
283
|
+
|
284
|
+
class Moon < Fire::SingleNestedModel
|
285
|
+
nested_in Earth
|
286
|
+
end
|
287
|
+
|
288
|
+
expect(->{
|
289
|
+
Moon.query
|
290
|
+
}).to raise_error(Fire::NestedModel::QueryingNotSupportedError)
|
291
|
+
end
|
292
|
+
|
293
|
+
|
269
294
|
end
|
270
295
|
|
271
296
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fire-model
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.11
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vitaly Tarasenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-06-
|
11
|
+
date: 2015-06-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: tarvit-helpers
|