motion-prime 0.5.4 → 0.5.5

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,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MDEyOWU0OGJhMGZmOGE2MTgyZjA0ZGYyNzlkYzA0MWJkZWE4NjI5YQ==
4
+ ZWI5NzE3MDI4ZThhZGM4ZTk4NGQ1NzhkZjFlYTNhZGJkY2Q0OTM2YQ==
5
5
  data.tar.gz: !binary |-
6
- NjI0YjU0MTAzM2I3OGRiODM2NTI2ZmVlOTdjZDdlMmU1ZjdlYjM4NQ==
6
+ NmRiZDc2ZGNlYjEzMDQ1M2QxMTk1ZGY1Nzg0MDYzOTgxOWMxNDUyNA==
7
7
  !binary "U0hBNTEy":
8
8
  metadata.gz: !binary |-
9
- ZmRmNDU1YThiN2QwZDM5YmVhZjhhZTNhZmVjNDYwZmVjYmE1ZDhmYWJiNWJk
10
- YmVhNWMwMGIzNzYwM2JmMzRmNmUwOWE3YmYwYzgzNmY3MmVmYjdmYjAxNjA5
11
- MmZhMGFiZWRiZWM4YmE2NDhhYmZjNmFkMjkwZDI5ODBmNzFkYjY=
9
+ ZGE4ZTcyOTA1MzQ5MTk5MTYyOWE5ZDRlMGEzNTczYjZlNzI5Y2NkMThmNzli
10
+ NzhmNjdjZmRjM2I4NmY2ZTAwNjAyOWY2NzJjZTE4ZGE1N2I0NjA3ZjNmZjAz
11
+ M2JiN2U1ODAzNTAyNjVkMDhiNTkxYzY1NjMyY2RiOTNmOWZhYWI=
12
12
  data.tar.gz: !binary |-
13
- MjFmOWYwNzg4ZDA5MzVlNjcyOTg2YWIyODlkM2ZhMmE5ZDcyNDJhZTRiMWEz
14
- YzAxYWM0ZTQ5N2QwNmJlOTgxY2M3ZDJmOWNiYzMzZTc2N2Y4YTBhZjA3ZGFh
15
- MjYzZTM0MjY1MTUyOTBkZmY2ODQ0NThlMDhlYTAwYTAzZjc5ZWU=
13
+ NzFjOGJjNTZlOWIyYjJhZDA5YmQ5MWQyM2JiYzdhMTk2NjVjMmY0MTFhZmE0
14
+ YWIwODQ4NmQ3MDJlYmRlZTVhNzUzNTE3OWY3MWEzOWZkYmY1MTYxNDQ0YWU0
15
+ YjVmODhkYzI4YWQ5MDE5MzUyNzc3MWNlYTYzNzZhNjM0NmY3ZjI=
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ {motion-prime}/**/*.rb
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ === 0.5.5
2
+ * improve association fetch speed and login.
3
+ * "delete" method is not supported for model collection now, use delete_all.
4
+
1
5
  === 0.5.4
2
6
  * ApiClient#authenticate returns full data and status instead of only token.
3
7
  * Made table cell more configuralble.
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- motion-prime (0.5.4)
4
+ motion-prime (0.5.5)
5
5
  bubble-wrap
6
6
  cocoapods
7
7
  methadone
data/README.md CHANGED
@@ -43,8 +43,8 @@ MotionPrime is yet another framework written on RubyMotion for creating really f
43
43
  title 'Main screen'
44
44
 
45
45
  def render
46
- @main_section = MyProfileSection.new(model: User.first)
47
- @main_section.render(to: self)
46
+ @main_section = MyProfileSection.new(screen: self)
47
+ @main_section.render
48
48
  end
49
49
  end
50
50
 
@@ -69,6 +69,7 @@ MotionPrime is yet another framework written on RubyMotion for creating really f
69
69
 
70
70
  * [ECSlidingViewController 2 integration](https://github.com/droidlabs/prime_sliding_menu) (Sidebar)
71
71
  * [RESideMenu integration](https://github.com/droidlabs/prime_reside_menu) (Sidebar)
72
+ * [Sliding actions support](https://github.com/droidlabs/prime_sliding_action)
72
73
 
73
74
  ## Samples
74
75
 
data/ROADMAP.md CHANGED
@@ -5,6 +5,7 @@
5
5
  * add more and better default options for fields
6
6
 
7
7
  === 0.7.0
8
+ * bug: if mp label do not have text and was set as hidden, it should unhide after setting text
8
9
  * add cleanup for section events
9
10
  * add dsl for push notifications
10
11
  * add some extensions/middleware system, at least for networking.
data/files/Gemfile CHANGED
@@ -5,7 +5,7 @@ gem 'motion-support', '~> 0.2.4'
5
5
  gem 'sugarcube', '~> 1.3.7', require: 'sugarcube-classic'
6
6
  gem 'bubble-wrap', '~> 1.4.0'
7
7
 
8
- gem 'motion-prime', '~> 0.5.3'
8
+ gem 'motion-prime', '~> 0.5.4'
9
9
 
10
10
  # add reside menu for sidebar support
11
11
  gem 'prime_reside_menu', '~> 0.1.3'
data/files/Gemfile.lock CHANGED
@@ -34,7 +34,7 @@ GEM
34
34
  bundler
35
35
  motion-cocoapods (1.4.0)
36
36
  cocoapods (>= 0.26.2)
37
- motion-prime (0.5.3)
37
+ motion-prime (0.5.4)
38
38
  bubble-wrap
39
39
  cocoapods
40
40
  methadone
@@ -67,7 +67,7 @@ PLATFORMS
67
67
  DEPENDENCIES
68
68
  bubble-wrap (~> 1.4.0)
69
69
  motion-cocoapods (~> 1.4.0)
70
- motion-prime (~> 0.5.3)
70
+ motion-prime (~> 0.5.4)
71
71
  motion-support (~> 0.2.4)
72
72
  prime_reside_menu (~> 0.1.3)
73
73
  sugarcube (~> 1.3.7)
@@ -6,7 +6,7 @@ Prime::Config.configure do |config|
6
6
 
7
7
  config.font.name = "Ubuntu"
8
8
 
9
- config.api do |api|
9
+ config.api_client do |api|
10
10
  api.base = "http://example.com"
11
11
  api.client_id = ""
12
12
  api.client_secret = ""
@@ -38,8 +38,9 @@ class ApiClient
38
38
  }
39
39
  use_callback = block_given?
40
40
  BW::HTTP.post("#{config.base}#{config.auth_path}", request_params(data)) do |response|
41
- auth_data = if response.ok?
42
- parse_json(response.body)
41
+ body = response.body.to_s
42
+ auth_data = if body.present?
43
+ parse_json(body)
43
44
  else
44
45
  false
45
46
  end
@@ -122,7 +123,7 @@ class ApiClient
122
123
  NSLog("Can't parse json: #{text}")
123
124
  false
124
125
  end
125
-
126
+
126
127
  def user_defaults
127
128
  @user_defaults ||= NSUserDefaults.standardUserDefaults
128
129
  end
@@ -12,7 +12,7 @@ module MotionPrime
12
12
  end
13
13
  end
14
14
 
15
- def normalize_object(object, receiver)
15
+ def normalize_object(object, receiver = nil)
16
16
  receiver ||= self
17
17
  if object.is_a?(Proc)
18
18
  receiver.send(:instance_exec, self, &object)
@@ -167,15 +167,25 @@ module MotionPrime
167
167
  self.store.count(self)
168
168
  end
169
169
 
170
- # Delete objects from store
170
+ # Delete objects from store by given options
171
+ #
172
+ # Examples:
173
+ # User.delete(:name => "Bob") #
171
174
  #
172
175
  # @param [Array, MotionPrime::Model] objects to delete
173
- # @return [Array] result
176
+ # @return [Array] removed item keys
174
177
  def delete(*args)
178
+ if args.blank?
179
+ raise "Using delete with no args is not allowed. Please use delete_all to delete all records"
180
+ end
175
181
  keys = find_keys(*args)
176
182
  self.store.delete_keys(keys)
177
183
  end
178
184
 
185
+ def delete_all
186
+ self.store.delete_keys(find_keys)
187
+ end
188
+
179
189
  def default_sort(sort_options)
180
190
  self.default_sort_options = sort_options
181
191
  end
@@ -14,6 +14,12 @@ module MotionPrime
14
14
  normalize_sync_url(url)
15
15
  end
16
16
 
17
+ def association_sync_url(key, options)
18
+ url = options[:sync_url]
19
+ url = url.call(self) if url.is_a?(Proc)
20
+ normalize_sync_url(url)
21
+ end
22
+
17
23
  # destroy on server and delete on local
18
24
  def destroy(&block)
19
25
  use_callback = block_given?
@@ -88,7 +94,7 @@ module MotionPrime
88
94
  post_data[model_name] = filtered_attributes
89
95
 
90
96
  method = options[:method] || (persisted? ? :put : :post)
91
- api_client.send(method, url, post_data) do |data, status_code|
97
+ api_client.send(method, url, post_data, options) do |data, status_code|
92
98
  save_response = !options.has_key?(:save_response) || options[:save_response]
93
99
  if save_response && status_code.to_s =~ /20\d/ && data.is_a?(Hash)
94
100
  set_attributes_from_response(data)
@@ -104,11 +110,14 @@ module MotionPrime
104
110
  end
105
111
 
106
112
  # set attributes, using fetch
107
- def fetch_with_attributes(attrs)
113
+ def fetch_with_attributes(attrs, sync_options = {})
108
114
  track_changed_attributes do
109
115
  attrs.each do |key, value|
110
116
  if respond_to?(:"fetch_#{key}")
111
117
  self.send(:"fetch_#{key}", value)
118
+ elsif has_association?(key) && (value.is_a?(Hash) || value.is_a?(Array))
119
+ should_save = sync_options[:save_associations]
120
+ fetch_association_with_attributes(key, value, save: should_save)
112
121
  elsif respond_to?(:"#{key}=")
113
122
  self.send(:"#{key}=", value)
114
123
  end
@@ -131,10 +140,14 @@ module MotionPrime
131
140
  end
132
141
  end
133
142
 
143
+ def has_association?(key)
144
+ !(self.class._associations || {})[key.to_sym].nil?
145
+ end
146
+
134
147
  def fetch_association?(key)
135
148
  options = self.class._associations[key]
136
- return if options[:if] && !options[:if].to_proc.call(self)
137
- options[:sync_url].present?
149
+ return false if options[:if] && !options[:if].to_proc.call(self)
150
+ association_sync_url(key, options).present?
138
151
  end
139
152
 
140
153
  def fetch_association(key, sync_options = {}, &block)
@@ -147,32 +160,23 @@ module MotionPrime
147
160
  end
148
161
  end
149
162
 
150
- def fetch_has_many(key, options = {}, sync_options = {}, &block)
151
- old_collection = self.send(key)
163
+ def fetch_association_with_attributes(key, data, sync_options = {})
164
+ options = (self.class._associations || {})[key.to_sym]
165
+ return unless options
166
+ if options[:type] == :many
167
+ fetch_has_many_with_attributes(key, data, sync_options)
168
+ else
169
+ fetch_has_one_with_attributes(key, data, sync_options)
170
+ end
171
+ end
152
172
 
173
+ def fetch_has_many(key, options = {}, sync_options = {}, &block)
153
174
  use_callback = block_given?
154
175
  NSLog("SYNC: started sync for #{key} in #{self.class_name_without_kvo}")
155
- api_client.get normalize_sync_url(options[:sync_url]) do |response, status_code|
176
+ api_client.get association_sync_url(key, options) do |response, status_code|
156
177
  data = options[:sync_key] && response ? response[options[:sync_key]] : response
157
- model_class = key.classify.constantize
158
178
  if data
159
- # Update/Create existing records
160
- data.each do |attributes|
161
- model = old_collection.detect{ |model| model.id == attributes[:id]}
162
- unless model
163
- model = model_class.new
164
- self.send(:"#{key}_bag") << model
165
- end
166
- model.fetch_with_attributes(attributes)
167
- model.save if sync_options[:save] && model.has_changed?
168
- end
169
- old_collection.each do |old_model|
170
- model = data.detect{ |model| model[:id] == old_model.id}
171
- unless model
172
- old_model.delete
173
- end
174
- end
175
- save if sync_options[:save]
179
+ fetch_has_many_with_attributes(key, data, sync_options)
176
180
  NSLog("SYNC: finished sync for #{key} in #{self.class_name_without_kvo}")
177
181
  block.call(data, status_code, response) if use_callback
178
182
  else
@@ -182,19 +186,37 @@ module MotionPrime
182
186
  end
183
187
  end
184
188
 
189
+ def fetch_has_many_with_attributes(key, data, sync_options = {})
190
+ old_collection = self.send(key)
191
+ model_class = key.classify.constantize
192
+ self.class.store.save_interval = data.count
193
+ # Update/Create existing records
194
+ data.each do |attributes|
195
+ model = old_collection.detect{ |model| model.id == attributes[:id]}
196
+ unless model
197
+ model = model_class.new
198
+ self.send(:"#{key}_bag") << model
199
+ end
200
+ model.fetch_with_attributes(attributes, save_associations: sync_options[:save])
201
+ model.save if sync_options[:save] && model.has_changed?
202
+ end
203
+ old_collection.each do |old_model|
204
+ model = data.detect{ |model| model[:id] == old_model.id}
205
+ unless model
206
+ old_model.delete
207
+ end
208
+ end
209
+ save if sync_options[:save]
210
+ self.class.store.save_interval = 1
211
+ end
212
+
185
213
  def fetch_has_one(key, options = {}, &block)
186
214
  use_callback = block_given?
187
215
  NSLog("SYNC: started sync for #{key} in #{self.class_name_without_kvo}")
188
- api_client.get normalize_sync_url(options[:sync_url]) do |response, status_code|
216
+ api_client.get association_sync_url(key, options) do |response, status_code|
189
217
  data = options.has_key?(:sync_key) ? response[options[:sync_key]] : response
190
218
  if data.present?
191
- model = self.send(key)
192
- unless model
193
- model = key.classify.constantize.new
194
- self.send(:"#{key}_bag") << model
195
- end
196
- model.fetch_with_attributes(data)
197
- model.save if sync_options[:save]
219
+ fetch_has_one_with_attributes(key, data, save_associations: sync_options[:save])
198
220
  block.call(data, status_code, response) if use_callback
199
221
  else
200
222
  NSLog("SYNC ERROR: failed sync for #{key} in #{self.class_name_without_kvo}")
@@ -203,6 +225,16 @@ module MotionPrime
203
225
  end
204
226
  end
205
227
 
228
+ def fetch_has_one_with_attributes(key, data, sync_options = {})
229
+ model = self.send(key)
230
+ unless model
231
+ model = key.classify.constantize.new
232
+ self.send(:"#{key}_bag") << model
233
+ end
234
+ model.fetch_with_attributes(data)
235
+ model.save if sync_options[:save]
236
+ end
237
+
206
238
  def filtered_updatable_attributes(options = {})
207
239
  slice_attributes = options[:updatable_attributes].map(&:to_sym) if options.has_key?(:updatable_attributes)
208
240
  updatable_attributes = self.class.updatable_attributes
@@ -235,7 +267,7 @@ module MotionPrime
235
267
  end
236
268
 
237
269
  def normalize_sync_url(url)
238
- url.to_s.gsub(':id', id.to_s)
270
+ normalize_object(url).to_s.gsub(':id', id.to_s)
239
271
  end
240
272
 
241
273
  module ClassMethods
@@ -75,5 +75,9 @@ module MotionPrime
75
75
  def model_class
76
76
  @model_class ||= @association_name.classify.constantize
77
77
  end
78
+
79
+ def delete_all
80
+ all.each { |obj| obj.delete }
81
+ end
78
82
  end
79
83
  end
@@ -10,6 +10,7 @@ motion_require './store_extension.rb'
10
10
  module MotionPrime
11
11
  class Model < NSFNanoObject
12
12
  include MotionPrime::HasAuthorization
13
+ include MotionPrime::HasNormalizer
13
14
  include MotionPrime::ModelBaseMixin
14
15
  include MotionPrime::ModelAssociationMixin
15
16
  include MotionPrime::ModelSyncMixin
@@ -57,14 +57,6 @@ class NSFNanoStore
57
57
  result
58
58
  end
59
59
 
60
- # Delete objects by keys
61
- def delete_keys(keys)
62
- error_ptr = Pointer.new(:id)
63
- success = self.store.removeObjectsWithKeysInArray(keys, error: error_ptr)
64
- raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
65
- result
66
- end
67
-
68
60
 
69
61
  # delete all objects from store
70
62
  def clear
@@ -21,6 +21,7 @@ module MotionPrime
21
21
  screen
22
22
  end
23
23
 
24
+ # @return screen [Prime::Screen] screen appearing after close
24
25
  def close_screen(args = {})
25
26
  args[:animated] = args.has_key?(:animated) ? args[:animated] : true
26
27
  # Pop current view, maybe with arguments, if in navigation controller
@@ -85,22 +86,33 @@ module MotionPrime
85
86
  navigation_controller.pushViewController(screen, animated: args[:animated])
86
87
  end
87
88
 
89
+ # @return screen [Prime::Screen] screen appearing after close
88
90
  def close_screen_modal(args = {})
89
91
  parent_screen.dismissViewControllerAnimated(args[:animated], completion: lambda {
90
92
  send_on_return(args)
91
93
  })
94
+ parent_screen
92
95
  end
93
96
 
97
+ # @return screen [Prime::Screen] screen appearing after close
94
98
  def close_screen_navigational(args = {})
95
99
  if args[:to_screen] && args[:to_screen].is_a?(UIViewController)
96
100
  self.parent_screen = args[:to_screen]
97
101
 
98
102
  screens = self.navigation_controller.childViewControllers
99
103
  self.navigation_controller.popToViewController(args[:to_screen], animated: args[:animated])
104
+ result = self.parent_screen
100
105
  else
101
- self.navigation_controller.popViewControllerAnimated(args[:animated])
106
+ if args[:to_root]
107
+ self.navigation_controller.popToRootViewControllerAnimated(args[:animated])
108
+ result = self.navigation_controller.childViewControllers.first
109
+ else
110
+ self.navigation_controller.popViewControllerAnimated(args[:animated])
111
+ result = self.navigation_controller.childViewControllers.last
112
+ end
102
113
  end
103
114
  send_on_return(args)
115
+ result
104
116
  end
105
117
 
106
118
  def wrap_in_navigation!
@@ -221,7 +221,9 @@ module MotionPrime
221
221
  elements = Array.wrap(keyboard_close_bindings_options[:elements])
222
222
  views = Array.wrap(keyboard_close_bindings_options[:views])
223
223
 
224
- elements.each { |el| views << el.view if %w[text_field text_view].include?(el.view_name) && el.view }
224
+ elements.each do |el|
225
+ views << el.view if %w[text_field text_view].include?(el.view_name) && el.view
226
+ end
225
227
  views.compact.each(&:resignFirstResponder)
226
228
  end
227
229
 
@@ -247,6 +249,7 @@ module MotionPrime
247
249
  end
248
250
 
249
251
  def keyboard_close_bindings_options
252
+ return {} unless self.class.keyboard_close_bindings.present?
250
253
  @keyboard_close_bindings_options ||= normalize_options(self.class.keyboard_close_bindings.clone, self)
251
254
  end
252
255
 
@@ -12,12 +12,13 @@ module MotionPrime
12
12
  def prepare_table_data
13
13
  @form = @options[:table]
14
14
  if options[:observe_errors]
15
- @errors_observer_options = normalize_options(options.delete(:observe_errors), self)
15
+ # Do not remove clone() after delete()
16
+ @errors_observer_options = normalize_options(options.delete(:observe_errors).clone, self)
16
17
  end
17
18
  end
18
19
 
19
20
  # Returns true if we should render element in current state
20
- #
21
+ #
21
22
  # @param element_name [Symbol] name of element in field
22
23
  # @return [Boolean]
23
24
  def render_element?(element_name)
@@ -31,7 +32,7 @@ module MotionPrime
31
32
  end
32
33
 
33
34
  # Changes height of the field (the cell in table) with animation.
34
- #
35
+ #
35
36
  # @param height [Integet] new height of field
36
37
  # @return [MotionPrime::BaseFieldSection]
37
38
  def update_height(height)
@@ -39,7 +40,7 @@ module MotionPrime
39
40
  field_index = form.field_indexes[name]
40
41
  index = field_index.split('_').map(&:to_i)
41
42
  path = NSIndexPath.indexPathForRow(index.last, inSection: index.first)
42
- form.table_view.reloadRowsAtIndexPaths([path], withRowAnimation: UITableViewRowAnimationNone)
43
+ form.table_view.reloadRowsAtIndexPaths([path], withRowAnimation: UITableViewRowAnimationFade)
43
44
  self
44
45
  end
45
46
 
@@ -250,7 +250,9 @@ module MotionPrime
250
250
  private
251
251
  def display_pending_cells
252
252
  table_view.visibleCells.each do |cell_view|
253
- cell_view.section.display if cell_view.section.pending_display
253
+ if cell_view.section && cell_view.section.pending_display
254
+ cell_view.section.display
255
+ end
254
256
  end
255
257
  end
256
258
 
@@ -1,3 +1,3 @@
1
1
  module MotionPrime
2
- VERSION = "0.5.4"
2
+ VERSION = "0.5.5"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: motion-prime
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.4
4
+ version: 0.5.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Iskander Haziev
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-21 00:00:00.000000000 Z
12
+ date: 2014-01-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -175,6 +175,7 @@ extra_rdoc_files: []
175
175
  files:
176
176
  - .gitignore
177
177
  - .travis.yml
178
+ - .yardopts
178
179
  - CHANGELOG.md
179
180
  - Gemfile
180
181
  - Gemfile.lock