fire-model 0.0.10 → 0.0.11
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 +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
|