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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: de9855aaa62f8486c88fd342c4e2fda217d042f0
4
- data.tar.gz: b1d04688dc786d1ffefb03d22a5e7ecd63a0082e
3
+ metadata.gz: 2f20e6ee2e52181a1490b86b89ac6fd856ef625d
4
+ data.tar.gz: 47ed6a3f6a15e509dcd8a0be087b45fd2b0d10a0
5
5
  SHA512:
6
- metadata.gz: dd9605004b7ee87c441f509f69ae328c6b2fd36ef9d9ddd50ef8096dfa2f7ef920da12a92fc227762f86a7f23bea977dbd4e987cf68d1e7dc52b6baa76e4157d
7
- data.tar.gz: cef9a05347474fd52edcd5844b92d7560a963698aa7d918e76b56dd54d38cf77aab5b6d4e8c94aa96bf100f5e6b148141f802689e8abdfcbb59a550c10dbf660
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, name: 'Kobzar', author: 'T.G. Shevchenko')
19
- LibraryBook.create(library: 'Shevchenko', floor: 1, row_number: 1, shelf: 15, name: 'Eneida', author: 'I. Kotlyrevskiy')
20
- LibraryBook.create(library: 'Shevchenko', floor: 2, row_number: 15, shelf: 115, name: 'Lord Of The Rings', author: ' J.R.R. Tolkien')
21
- LibraryBook.create(library: 'Skovoroda', floor: 1, row_number: 25, shelf: 34, name: 'Harry Potter', author: 'J.K. Rowling')
22
- LibraryBook.create(library: 'Skovoroda', floor: 2, row_number: 12, shelf: 15, name: 'Hobbit', author: ' J.R.R. Tolkien')
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.connection.get(?/).body
135
+ Fire.tree
129
136
  => {'Organization'=>
130
- {'usa'=>
131
- {'ca'=>
132
- {'apple'=>
133
- {'country'=>'USA',
134
- 'employees'=>
135
- {'hq'=>
136
- {'h543ka'=>
137
- {'department'=>'HQ',
138
- 'full_name'=>'Tim Cook',
139
- 'id'=>'h543ka',
140
- 'position'=>'CEO'}}},
141
- 'name'=>'Apple',
142
- 'state'=>'CA'},
143
- 'google'=>
144
- {'country'=>'USA',
145
- 'employees'=>
146
- {'research'=>
147
- {'d23h1a'=>
148
- {'department'=>'Research',
149
- 'full_name'=>'Larry Page',
150
- 'id'=>'d23h1a',
151
- 'position'=>'CEO'}}},
152
- 'name'=>'Google',
153
- 'state'=>'CA'}}}}}
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.10
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.10 ruby lib
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.10"
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-20"
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
@@ -20,6 +20,10 @@ module Fire
20
20
  connection.delete(?/)
21
21
  end
22
22
 
23
+ def self.tree
24
+ connection.get(?/).body
25
+ end
26
+
23
27
  def self.connection
24
28
  Fire::Connection::Request.new
25
29
  end
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
- include Querying
221
+
203
222
  include NestedModel::Parent
204
223
  end
205
224
  end
@@ -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
@@ -15,7 +15,9 @@ module Fire
15
15
 
16
16
  folder = nested_model.folder
17
17
  define_method "nested_#{folder}" do
18
- nested_model.folder_content(self)
18
+ self.cache(folder) do
19
+ nested_model.folder_content(self)
20
+ end
19
21
  end
20
22
 
21
23
  define_method "add_to_#{folder}" do |object|
@@ -9,7 +9,8 @@ module Fire
9
9
  end
10
10
 
11
11
  def folder_content(parent)
12
- new(parent.send(folder).merge(parent.path_data))
12
+ object = parent.send(folder) || {}
13
+ new(object.merge(parent.path_data))
13
14
  end
14
15
 
15
16
  protected
@@ -12,7 +12,8 @@ module Fire
12
12
  response = connection.get(full_path).body
13
13
  return [] if response.nil?
14
14
 
15
- rows = down_levels(response, (own_path_keys - direct_keys).count)
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
@@ -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 = 6
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
- before :each do
6
- Fire.drop!
7
- end
8
-
9
- after :each do
10
- Fire.drop!
11
- end
5
+ context 'With Firebase Connection' do
12
6
 
13
- it 'should declare nested models' do
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
- expect(Organization.nested_models).to be_empty
11
+ after :each do
12
+ Fire.drop!
13
+ end
21
14
 
22
- class Employee < Fire::NestedModel
23
- nested_in Organization
24
- has_path_keys :department
15
+ def current_data
16
+ Fire.tree
25
17
  end
26
18
 
27
- expect(Organization.nested_models).to eq([ Employee ])
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
- context 'Nested Models Types' do
21
+ class Organization < Fire::Model
22
+ has_path_keys :country, :state
23
+ set_id_key(:name)
24
+ end
118
25
 
119
- it 'should declare single nested models' do
26
+ expect(Organization.nested_models).to be_empty
120
27
 
121
- class Car < Fire::Model
122
- has_path_keys :manufacturer, :model, :car_class
28
+ class Employee < Fire::NestedModel
29
+ nested_in Organization
30
+ has_path_keys :department
123
31
  end
124
32
 
125
- class Engine < Fire::SingleNestedModel
126
- nested_in Car
127
- end
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
- scirocco = Car.create(manufacturer: 'Volkswagen', model: 'Scirocco', car_class: 'Sport compact')
130
- scirocco.add_to_engine(code: 'I4 turbo', power: '122 PS')
131
-
132
- car = Car.create(manufacturer: 'Zaporozhets', model: 'ZAZ-965', car_class: 'Mini', engine: { code: 'MeMZ-966' })
133
-
134
- zaporozhets = Car.take(manufacturer: 'Zaporozhets', model: 'ZAZ-965', car_class: 'Mini', id: car.id)
135
- expect(zaporozhets.nested_engine.code).to eq('MeMZ-966')
136
-
137
- expect(current_data).to eq({
138
- 'Car'=>
139
- {'volkswagen'=>
140
- {'scirocco'=>
141
- {'sport-compact'=>
142
- {scirocco.id=>
143
- {'''car_class'=>'Sport compact',
144
- 'engine'=>{'code'=>'I4 turbo', 'power'=>'122 PS'},
145
- 'id'=>scirocco.id,
146
- 'manufacturer'=>'Volkswagen',
147
- 'model'=>'Scirocco'}}}},
148
- 'zaporozhets'=>
149
- {'zaz-965'=>
150
- {'mini'=>
151
- {zaporozhets.id=>
152
- {'car_class'=>'Mini',
153
- 'engine'=>{'code'=>'MeMZ-966'},
154
- 'id'=>zaporozhets.id,
155
- 'manufacturer'=>'Zaporozhets',
156
- 'model'=>'ZAZ-965'}}}}}})
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
- it 'should allow to declare nested models with all *parent values* duplicated' do
160
- class House < Fire::Model
161
- has_path_keys :country, :city, :street
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
- class Room < Fire::NestedModel
166
- nested_in House, parent_values: true
167
- set_id_key(:number)
168
- has_path_keys :floor
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
- house = House.create(country: 'Ukraine', city: 'Kyiv', street: 'Shevchenko Ave.', house_number: '53101')
172
- house.add_to_rooms(floor: 200, number: '1A')
173
- house.add_to_rooms(floor: 150, number: '2A')
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
- house = House.query(house_number: '53101').first
176
- rooms = house.nested_rooms
177
- expect(rooms.map(&:number).sort).to eq(%w{ 1A 2A }.sort)
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
- expect(current_data).to eq(
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
- def current_data
268
- Fire.connection.get(?/).body
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.10
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-20 00:00:00.000000000 Z
11
+ date: 2015-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: tarvit-helpers