motion-prime 0.5.4 → 0.5.5

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