Module: MotionPrime::ModelSyncMixin
- Extended by:
- MotionSupport::Concern
- Included in:
- Model
- Defined in:
- motion-prime/models/_sync_mixin.rb
Defined Under Namespace
Modules: ClassMethods
Class Method Summary collapse
Instance Method Summary collapse
-
#association_sync_url(key, options, sync_options = {}) ⇒ Object
Get normalized sync url of associated Prime::Model.
- #associations ⇒ Object
- #associations_to_fetch(options = {}) ⇒ Object
- #attributes_to_post_data(root_name, attributes) ⇒ Object
-
#destroy(&block) ⇒ Object
Destroy model on server and delete on local.
-
#fetch(options = {}, &block) ⇒ Object
Fetch model from server.
-
#fetch!(options = {}, &block) ⇒ Object
Fetch model from server and save on local.
- #fetch_association(key, sync_options = {}, &block) ⇒ Object
- #fetch_association?(key, options = {}) ⇒ Boolean
- #fetch_association_with_attributes(key, data, sync_options = {}) ⇒ Object
- #fetch_associations(sync_options = {}, &block) ⇒ Object
- #fetch_has_many(key, options = {}, sync_options = {}, &block) ⇒ Object
- #fetch_has_many_with_attributes(key, data, sync_options = {}) ⇒ Object
- #fetch_has_one(key, options = {}, sync_options = {}, &block) ⇒ Object
- #fetch_has_one_with_attributes(key, data, sync_options = {}) ⇒ Object
-
#fetch_with_attributes(attrs, options = {}) ⇒ Object
Assign model attributes, using fetch.
-
#fetch_with_url(url, options = {}, &block) ⇒ Object
Fetch model from server using url.
- #filtered_updatable_attributes(options = {}) ⇒ Object
- #has_association?(key) ⇒ Boolean
- #has_associations_to_fetch?(options = {}) ⇒ Boolean
- #normalize_sync_url(url) ⇒ Object
- #set_attributes_from_response(data) ⇒ Object
-
#sync_url(method = :get, options = {}) ⇒ Object
Get normalized sync url of this Prime::Model.
-
#update(options = {}, &block) ⇒ Object
Update on server.
-
#update!(options = {}, &block) ⇒ Object
Update on server and save response on local.
-
#update_with_url(url, options = {}, &block) ⇒ Object
Update on server using url.
Class Method Details
.included(base) ⇒ Object
5 6 7 8 9 |
# File 'motion-prime/models/_sync_mixin.rb', line 5 def self.included(base) base.class_attribute :_sync_url base.class_attribute :_updatable_attributes base.class_attribute :_associations end |
Instance Method Details
#association_sync_url(key, options, sync_options = {}) ⇒ Object
Get normalized sync url of associated Prime::Model
25 26 27 28 29 |
# File 'motion-prime/models/_sync_mixin.rb', line 25 def association_sync_url(key, , = {}) url = [:sync_url] url = url.call(self, ) if url.is_a?(Proc) normalize_sync_url(url) end |
#associations ⇒ Object
175 176 177 |
# File 'motion-prime/models/_sync_mixin.rb', line 175 def associations @associations ||= (self.class._associations || {}).clone end |
#associations_to_fetch(options = {}) ⇒ Object
179 180 181 |
# File 'motion-prime/models/_sync_mixin.rb', line 179 def associations_to_fetch( = {}) associations.select { |key, v| fetch_association?(key, ) } end |
#attributes_to_post_data(root_name, attributes) ⇒ Object
327 328 329 330 331 332 333 334 335 336 337 338 339 |
# File 'motion-prime/models/_sync_mixin.rb', line 327 def attributes_to_post_data(root_name, attributes) result = {:_files => [], root_name => attributes} result[root_name].each do |name, field_attrs| next unless field_attrs.is_a?(Hash) files = Array.wrap(field_attrs.delete(:_files)).map do |file| file[:name].insert(0, "#{root_name}[#{name}]") file end result[:_files] += files end result end |
#destroy(&block) ⇒ Object
Destroy model on server and delete on local
35 36 37 38 39 40 41 |
# File 'motion-prime/models/_sync_mixin.rb', line 35 def destroy(&block) use_callback = block_given? api_client.delete(sync_url(:delete)) do block.call() if use_callback end delete end |
#fetch(options = {}, &block) ⇒ Object
Fetch model from server
56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'motion-prime/models/_sync_mixin.rb', line 56 def fetch( = {}, &block) use_callback = block_given? method = [:method] || :get url = sync_url(method, ) will_fetch_model = !url.blank? will_fetch_associations = .fetch(:associations, true) will_fetch_associations = false unless has_associations_to_fetch?() fetch_with_url url, do |data, status_code| save if [:save] block.call(data, status_code, data) if use_callback && !will_fetch_associations end if will_fetch_model fetch_associations() do |data, status_code| # run callback only if it wasn't run on fetch block.call(data, status_code, data) if use_callback end if will_fetch_associations end |
#fetch!(options = {}, &block) ⇒ Object
Fetch model from server and save on local
45 46 47 |
# File 'motion-prime/models/_sync_mixin.rb', line 45 def fetch!( = {}, &block) fetch(.merge(save: true), &block) end |
#fetch_association(key, sync_options = {}, &block) ⇒ Object
211 212 213 214 215 216 217 218 219 |
# File 'motion-prime/models/_sync_mixin.rb', line 211 def fetch_association(key, = {}, &block) return unless fetch_association?(key, ) = associations[key.to_sym] if [:type] == :many fetch_has_many(key, , , &block) else fetch_has_one(key, , , &block) end end |
#fetch_association?(key, options = {}) ⇒ Boolean
202 203 204 205 206 207 208 209 |
# File 'motion-prime/models/_sync_mixin.rb', line 202 def fetch_association?(key, = {}) allowed_associations = [:associations].map(&:to_sym) if [:associations].is_a?(Array) return false if allowed_associations.try(:exclude?, key.to_sym) = associations[key.to_sym] return false if [:if] && ![:if].to_proc.call(self) association_sync_url(key, ).present? end |
#fetch_association_with_attributes(key, data, sync_options = {}) ⇒ Object
221 222 223 224 225 226 227 228 229 |
# File 'motion-prime/models/_sync_mixin.rb', line 221 def fetch_association_with_attributes(key, data, = {}) = associations[key.to_sym] return unless if [:type] == :many fetch_has_many_with_attributes(key, data || [], ) else fetch_has_one_with_attributes(key, data || {}, ) end end |
#fetch_associations(sync_options = {}, &block) ⇒ Object
183 184 185 186 187 188 189 190 191 192 |
# File 'motion-prime/models/_sync_mixin.rb', line 183 def fetch_associations( = {}, &block) use_callback = block_given? associations_to_fetch().keys.each_with_index do |key, index| if use_callback && associations.count - 1 == index fetch_association(key, , &block) else fetch_association(key, ) end end end |
#fetch_has_many(key, options = {}, sync_options = {}, &block) ⇒ Object
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'motion-prime/models/_sync_mixin.rb', line 231 def fetch_has_many(key, = {}, = {}, &block) use_callback = block_given? NSLog("SYNC: started sync for #{key} in #{self.class_name_without_kvo}") api_client.get association_sync_url(key, , ) do |response, status_code| data = [:sync_key] && response ? response[[:sync_key]] : response if data fetch_has_many_with_attributes(key, data, ) NSLog("SYNC: finished sync for #{key} in #{self.class_name_without_kvo}") block.call(data, status_code, response) if use_callback else NSLog("SYNC ERROR: failed sync for #{key} in #{self.class_name_without_kvo}") block.call(data, status_code, response) if use_callback end end end |
#fetch_has_many_with_attributes(key, data, sync_options = {}) ⇒ Object
247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 |
# File 'motion-prime/models/_sync_mixin.rb', line 247 def fetch_has_many_with_attributes(key, data, = {}) old_collection = self.send(key) model_class = key.classify.constantize self.store.save_interval = data.present? ? data.count : 1 # Update/Create existing records track_changed_attributes do data.each do |attributes| model = old_collection.detect{ |model| model.id == attributes[:id]} unless model model = model_class.new self.send(key).add(model) end model.fetch_with_attributes(attributes, save_associations: [:save]) model.save if [:save] && model.has_changed? end old_collection.each do |old_model| model = data.detect{ |model| model[:id] == old_model.id} unless model old_model.delete end end unless [:append] end save if [:save] && has_changed? self.store.save_interval = 1 end |
#fetch_has_one(key, options = {}, sync_options = {}, &block) ⇒ Object
273 274 275 276 277 278 279 280 281 282 283 284 285 286 |
# File 'motion-prime/models/_sync_mixin.rb', line 273 def fetch_has_one(key, = {}, = {}, &block) use_callback = block_given? NSLog("SYNC: started sync for #{key} in #{self.class_name_without_kvo}") api_client.get association_sync_url(key, , ) do |response, status_code| data = .has_key?(:sync_key) ? response[[:sync_key]] : response if data.present? fetch_has_one_with_attributes(key, data, save_associations: [:save]) block.call(data, status_code, response) if use_callback else NSLog("SYNC ERROR: failed sync for #{key} in #{self.class_name_without_kvo}") block.call(data, status_code, response) if use_callback end end end |
#fetch_has_one_with_attributes(key, data, sync_options = {}) ⇒ Object
288 289 290 291 292 293 294 295 296 297 298 299 |
# File 'motion-prime/models/_sync_mixin.rb', line 288 def fetch_has_one_with_attributes(key, data, = {}) track_changed_attributes do model = self.send(key) unless model model = key.classify.constantize.new self.send(:"#{key}_bag") << model end model.fetch_with_attributes(data) model.save if [:save] end save if [:save] && has_changed? end |
#fetch_with_attributes(attrs, options = {}) ⇒ Object
Assign model attributes, using fetch. Differenct between assign_attributes and fetch_with_attributes is ths you can create method named fetch_:attribute and it will be used to assign attribute only on fetch.
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 |
# File 'motion-prime/models/_sync_mixin.rb', line 159 def fetch_with_attributes(attrs, = {}) track_changed_attributes do attrs.each do |key, value| if respond_to?(:"fetch_#{key}") self.send(:"fetch_#{key}", value) elsif has_association?(key) && (value.is_a?(Hash) || value.is_a?(Array)) should_save = [:save_associations] fetch_association_with_attributes(key, value, save: should_save) elsif respond_to?(:"#{key}=") self.send(:"#{key}=", value) end end end self end |
#fetch_with_url(url, options = {}, &block) ⇒ Object
Fetch model from server using url
102 103 104 105 106 107 108 109 110 |
# File 'motion-prime/models/_sync_mixin.rb', line 102 def fetch_with_url(url, = {}, &block) use_callback = block_given? api_client.get(url) do |data, status_code| if data.present? fetch_with_attributes(data, save_associations: [:save], &block) end block.call(data, status_code, data) if use_callback end end |
#filtered_updatable_attributes(options = {}) ⇒ Object
301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 |
# File 'motion-prime/models/_sync_mixin.rb', line 301 def filtered_updatable_attributes( = {}) slice_attributes = [:updatable_attributes].map(&:to_sym) if .has_key?(:updatable_attributes) updatable_attributes = self.class.updatable_attributes if updatable_attributes.blank? return slice_attributes ? attributes_hash.slice(*slice_attributes) : attributes_hash end updatable_attributes = updatable_attributes.slice(*slice_attributes) if slice_attributes updatable_attributes.inject({}) do |hash, (key, )| next hash if [:if] && !send([:if]) value = if block = [:block] block.call(self, hash) else info[key] end hash[key] = value hash end end |
#has_association?(key) ⇒ Boolean
198 199 200 |
# File 'motion-prime/models/_sync_mixin.rb', line 198 def has_association?(key) !associations[key.to_sym].nil? end |
#has_associations_to_fetch?(options = {}) ⇒ Boolean
194 195 196 |
# File 'motion-prime/models/_sync_mixin.rb', line 194 def has_associations_to_fetch?( = {}) associations_to_fetch().present? end |
#normalize_sync_url(url) ⇒ Object
323 324 325 |
# File 'motion-prime/models/_sync_mixin.rb', line 323 def normalize_sync_url(url) normalize_object(url).to_s.gsub(':id', id.to_s) end |
#set_attributes_from_response(data) ⇒ Object
136 137 138 139 |
# File 'motion-prime/models/_sync_mixin.rb', line 136 def set_attributes_from_response(data) self.id ||= data.delete('id') fetch_with_attributes(data) end |
#sync_url(method = :get, options = {}) ⇒ Object
Get normalized sync url of this Prime::Model
15 16 17 18 19 |
# File 'motion-prime/models/_sync_mixin.rb', line 15 def sync_url(method = :get, = {}) url = self.class.sync_url url = url.call(method, self, ) if url.is_a?(Proc) normalize_sync_url(url) end |
#update(options = {}, &block) ⇒ Object
Update on server
86 87 88 89 90 91 92 93 94 95 96 |
# File 'motion-prime/models/_sync_mixin.rb', line 86 def update( = {}, &block) use_callback = block_given? method = [:method] || (persisted? ? :put : :post) url = sync_url(method, ) will_update_model = !url.blank? update_with_url url, do |data, status_code| block.call(data, status_code, data) if use_callback end if will_update_model end |
#update!(options = {}, &block) ⇒ Object
Update on server and save response on local
78 79 80 |
# File 'motion-prime/models/_sync_mixin.rb', line 78 def update!( = {}, &block) update(.merge(save_response: true), &block) end |
#update_with_url(url, options = {}, &block) ⇒ Object
Update on server using url
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
# File 'motion-prime/models/_sync_mixin.rb', line 116 def update_with_url(url, = {}, &block) use_callback = block_given? filtered_attributes = filtered_updatable_attributes() attributes = attributes_to_post_data(model_name, filtered_attributes) post_data = [:params_root] || {} post_data.merge!(attributes) method = [:method] || (persisted? ? :put : :post) api_client.send(method, url, post_data, ) do |data, status_code| save_response = !.has_key?(:save_response) || [:save_response] if save_response && status_code.to_s =~ /20\d/ && data.is_a?(Hash) set_attributes_from_response(data) save end block.call(data, status_code, data) if use_callback end end |