motion-prime 0.2.1 → 0.3.0
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 +8 -8
- data/CHANGELOG.md +5 -0
- data/Gemfile.lock +14 -11
- data/README.md +8 -11
- data/Rakefile +2 -1
- data/bin/prime.rb +47 -0
- data/doc/FAQ.md +1 -1
- data/files/app/app_delegate.rb +1 -1
- data/files/app/config/base.rb +8 -4
- data/files/app/screens/application_screen.rb +1 -1
- data/files/app/screens/sidebar_screen.rb +1 -1
- data/files/app/sections/sidebar/action.rb +1 -1
- data/files/app/sections/sidebar/table.rb +1 -1
- data/files/app/styles/sidebar.rb +5 -5
- data/motion-prime.gemspec +1 -0
- data/motion-prime/api_client.rb +81 -0
- data/motion-prime/app_delegate.rb +22 -5
- data/motion-prime/config/base.rb +5 -0
- data/motion-prime/core_ext/kernel.rb +5 -0
- data/motion-prime/elements/_field_dimensions_mixin.rb +43 -0
- data/motion-prime/elements/_text_dimensions_mixin.rb +39 -0
- data/motion-prime/elements/base.rb +40 -17
- data/motion-prime/elements/button.rb +20 -0
- data/motion-prime/elements/draw.rb +2 -2
- data/motion-prime/elements/draw/image.rb +4 -2
- data/motion-prime/elements/draw/label.rb +1 -1
- data/motion-prime/elements/error_message.rb +3 -16
- data/motion-prime/elements/label.rb +13 -2
- data/motion-prime/elements/text_field.rb +1 -0
- data/motion-prime/helpers/cell_section.rb +9 -0
- data/motion-prime/helpers/has_authorization.rb +4 -3
- data/motion-prime/helpers/has_normalizer.rb +20 -6
- data/motion-prime/helpers/has_search_bar.rb +19 -7
- data/motion-prime/helpers/has_style_chain_builder.rb +7 -0
- data/motion-prime/models/association.rb +22 -9
- data/motion-prime/models/association_collection.rb +54 -23
- data/motion-prime/models/bag.rb +13 -12
- data/motion-prime/models/base.rb +2 -0
- data/motion-prime/models/errors.rb +23 -14
- data/motion-prime/models/finder.rb +4 -1
- data/motion-prime/models/model.rb +25 -5
- data/motion-prime/models/store_extension.rb +1 -7
- data/motion-prime/models/sync.rb +75 -43
- data/motion-prime/mp.rb +4 -0
- data/motion-prime/screens/_base_mixin.rb +18 -12
- data/motion-prime/screens/_navigation_bar_mixin.rb +15 -6
- data/motion-prime/screens/_navigation_mixin.rb +15 -16
- data/motion-prime/screens/base_screen.rb +5 -1
- data/motion-prime/screens/sidebar_container_screen.rb +37 -22
- data/motion-prime/sections/base.rb +82 -16
- data/motion-prime/sections/form.rb +144 -26
- data/motion-prime/sections/form/base_field_section.rb +62 -29
- data/motion-prime/sections/form/base_header_section.rb +27 -0
- data/motion-prime/sections/form/date_field_section.rb +2 -17
- data/motion-prime/sections/form/password_field_section.rb +3 -17
- data/motion-prime/sections/form/select_field_section.rb +4 -35
- data/motion-prime/sections/form/string_field_section.rb +3 -29
- data/motion-prime/sections/form/submit_field_section.rb +1 -7
- data/motion-prime/sections/form/switch_field_section.rb +3 -23
- data/motion-prime/sections/form/text_field_section.rb +3 -33
- data/motion-prime/sections/form/text_with_button_field_section.rb +4 -40
- data/motion-prime/sections/tabbed.rb +25 -5
- data/motion-prime/sections/table.rb +86 -22
- data/motion-prime/sections/table/refresh_mixin.rb +3 -1
- data/motion-prime/styles/base.rb +7 -89
- data/motion-prime/styles/form.rb +116 -0
- data/motion-prime/support/dm_button.rb +32 -5
- data/motion-prime/support/dm_text_field.rb +31 -7
- data/motion-prime/support/dm_text_view.rb +6 -3
- data/motion-prime/support/dm_view_controller.rb +3 -3
- data/motion-prime/support/ui_search_bar_custom.rb +1 -1
- data/motion-prime/version.rb +1 -1
- data/motion-prime/views/layout.rb +18 -10
- data/motion-prime/views/styles.rb +19 -9
- data/motion-prime/views/view_builder.rb +18 -2
- data/motion-prime/views/view_styler.rb +59 -5
- data/spec/models/errors_spec.rb +3 -3
- data/travis.sh +3 -2
- metadata +28 -5
- data/motion-prime/elements/_text_height_mixin.rb +0 -17
- data/motion-prime/sections/form/table_field_section.rb +0 -51
@@ -18,17 +18,15 @@ module MotionPrime
|
|
18
18
|
# @param [String] name - the name of bag
|
19
19
|
# @return [Nil]
|
20
20
|
def bag(name)
|
21
|
-
klass = self
|
22
|
-
|
23
21
|
define_method(name) do |*args, &block|
|
24
22
|
return _bags[name] if _bags[name]
|
25
|
-
|
26
23
|
bag_key = self.info[name]
|
27
|
-
if bag_key.
|
24
|
+
if bag_key.present?
|
25
|
+
bag = self.class.store.bagsWithKeysInArray([bag_key]).first
|
26
|
+
end
|
27
|
+
unless bag
|
28
28
|
bag = Bag.bag
|
29
29
|
self.info[name] = bag.key
|
30
|
-
else
|
31
|
-
bag = self.class.store.bagsWithKeysInArray([bag_key]).first
|
32
30
|
end
|
33
31
|
|
34
32
|
_bags[name] = bag
|
@@ -109,13 +107,28 @@ module MotionPrime
|
|
109
107
|
self.send(bag_name).clear
|
110
108
|
self.send(:"#{bag_name}=", value)
|
111
109
|
end
|
112
|
-
define_method("#{association_name}") do |
|
110
|
+
define_method("#{association_name}") do |*args|
|
113
111
|
bag = self.send(:"#{bag_name}")
|
114
112
|
collection_options = {
|
115
|
-
association_name: association_name
|
113
|
+
association_name: association_name,
|
114
|
+
inverse_relation: {
|
115
|
+
type: :has_one,
|
116
|
+
name: self.class_name_without_kvo.demodulize.underscore,
|
117
|
+
instance: self
|
118
|
+
}
|
116
119
|
}
|
117
|
-
AssociationCollection.new(bag, collection_options,
|
120
|
+
AssociationCollection.new(bag, collection_options, *args)
|
118
121
|
end
|
119
122
|
end
|
123
|
+
|
124
|
+
def belongs_to(association_name, options = {})
|
125
|
+
self._associations ||= {}
|
126
|
+
self._associations[association_name] = {
|
127
|
+
type: :belongs_to_one,
|
128
|
+
class_name: association_name.classify
|
129
|
+
}.merge(options)
|
130
|
+
|
131
|
+
self.send(:attr_accessor, association_name)
|
132
|
+
end
|
120
133
|
end
|
121
134
|
end
|
@@ -1,39 +1,70 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
class AssociationCollection < ::Array
|
3
|
-
attr_reader :bag
|
3
|
+
attr_reader :bag, :association_name
|
4
|
+
attr_reader :inverse_relation_name, :inverse_relation_key, :model_inverse_relation_name
|
4
5
|
|
5
6
|
delegate :<<, to: :bag
|
6
7
|
|
7
|
-
def initialize(bag, options,
|
8
|
+
def initialize(bag, options, *args)
|
8
9
|
@bag = bag
|
9
10
|
@association_name = options[:association_name]
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
11
|
+
bag.bare_class = model_class
|
12
|
+
|
13
|
+
inverse_relation_options = options[:inverse_relation]
|
14
|
+
define_inverse_relation(inverse_relation_options)
|
15
|
+
|
16
|
+
@model_inverse_relation_name = (model_class._associations || {}).find do |name, options|
|
17
|
+
options[:class_name] == inverse_relation.class_name_without_kvo
|
18
|
+
end.try(:first)
|
19
|
+
|
20
|
+
super all(*args)
|
21
|
+
end
|
22
|
+
|
23
|
+
def new(attributes = {})
|
24
|
+
model_class.new(attributes).tap do |model|
|
25
|
+
set_inverse_relation_for(model)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def define_inverse_relation(options)
|
30
|
+
# TODO: handle different relation types (habtm, has_one...)
|
31
|
+
@inverse_relation_name = name = options[:name].to_sym
|
32
|
+
self.class_eval do
|
33
|
+
define_method name do
|
34
|
+
options[:instance]
|
29
35
|
end
|
36
|
+
alias_method :inverse_relation, name
|
30
37
|
end
|
38
|
+
|
39
|
+
@inverse_relation_key = inverse_relation._associations[association_name][:foreign_key].try(:to_sym)
|
40
|
+
end
|
41
|
+
|
42
|
+
def all(*args)
|
43
|
+
return [] unless bag.store.present?
|
44
|
+
data = bag.find(find_options(args[0]), sort_options(args[1]))
|
45
|
+
set_inverse_relation_for(data)
|
31
46
|
data
|
32
47
|
end
|
33
48
|
|
49
|
+
def set_inverse_relation_for(models)
|
50
|
+
[*models].each do |model|
|
51
|
+
model.send("#{inverse_relation_name}=", inverse_relation)
|
52
|
+
end if model_inverse_relation_name.present?
|
53
|
+
end
|
54
|
+
|
55
|
+
def find_options(options)
|
56
|
+
options ||= {}
|
57
|
+
options.merge!(bag_key: bag.key)
|
58
|
+
if inverse_relation_key.present?
|
59
|
+
{inverse_relation_key => inverse_relation.id}.merge options
|
60
|
+
else
|
61
|
+
options
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
34
65
|
def sort_options(options)
|
35
|
-
return options if options
|
36
|
-
model_class.default_sort_options
|
66
|
+
return options if options.present?
|
67
|
+
{sort: model_class.default_sort_options}
|
37
68
|
end
|
38
69
|
|
39
70
|
def model_class
|
data/motion-prime/models/bag.rb
CHANGED
@@ -27,30 +27,30 @@ module MotionPrime
|
|
27
27
|
self.savedObjects.values + self.unsavedObjects.values
|
28
28
|
end
|
29
29
|
|
30
|
-
# Add an object to bag
|
31
|
-
#
|
32
|
-
# @return self
|
33
|
-
def <<(object)
|
34
|
-
error_ptr = Pointer.new(:id)
|
35
|
-
self.addObject(object, error:error_ptr)
|
36
|
-
raise StoreError, error_ptr[0].description if error_ptr[0]
|
37
|
-
self
|
38
|
-
end
|
39
|
-
|
40
30
|
# Add an object or array of objects to bag
|
41
31
|
#
|
42
32
|
# @return self
|
43
33
|
def add(object_or_array)
|
44
34
|
error_ptr = Pointer.new(:id)
|
45
35
|
if object_or_array.is_a?(Array)
|
46
|
-
self.addObjectsFromArray(object_or_array, error:error_ptr)
|
36
|
+
self.addObjectsFromArray(prepare_for_store(object_or_array), error:error_ptr)
|
47
37
|
else
|
48
|
-
self.addObject(object_or_array, error:error_ptr)
|
38
|
+
self.addObject(prepare_for_store(object_or_array), error:error_ptr)
|
49
39
|
end
|
50
40
|
raise StoreError, error_ptr[0].description if error_ptr[0]
|
51
41
|
self
|
52
42
|
end
|
53
43
|
alias_method :+, :add
|
44
|
+
alias_method :<<, :add
|
45
|
+
|
46
|
+
def prepare_for_store(object)
|
47
|
+
if object.is_a?(Array)
|
48
|
+
object.map { |entity| prepare_for_store(entity) }
|
49
|
+
else
|
50
|
+
object.bag_key = self.key
|
51
|
+
object
|
52
|
+
end
|
53
|
+
end
|
54
54
|
|
55
55
|
# Remove object from bag with key
|
56
56
|
#
|
@@ -126,5 +126,6 @@ module MotionPrime
|
|
126
126
|
end
|
127
127
|
|
128
128
|
class NSFNanoBag
|
129
|
+
include MotionPrime::ModelFinderMethods
|
129
130
|
include MotionPrime::BagInstanceMethods
|
130
131
|
end
|
data/motion-prime/models/base.rb
CHANGED
@@ -18,6 +18,8 @@ module MotionPrime
|
|
18
18
|
extend MotionPrime::ModelAssociationClassMethods
|
19
19
|
extend MotionPrime::ModelSyncClassMethods
|
20
20
|
|
21
|
+
attribute :bag_key # need this as we use shared store; each nested resource must belong to parent bag
|
22
|
+
|
21
23
|
def errors
|
22
24
|
@errors ||= Errors.new(self)
|
23
25
|
end
|
@@ -1,35 +1,40 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
class Errors
|
3
|
-
attr_accessor :
|
3
|
+
attr_accessor :_unique_keys
|
4
4
|
|
5
5
|
def initialize(model)
|
6
|
-
@
|
6
|
+
@_unique_keys = []
|
7
|
+
@model = model
|
7
8
|
model.class.attributes.map(&:to_sym).each do |key|
|
8
9
|
initialize_for_key key
|
9
10
|
end
|
10
11
|
end
|
11
12
|
|
13
|
+
def unique_key(key)
|
14
|
+
[key, @model.object_id].join('_').to_sym
|
15
|
+
end
|
16
|
+
|
12
17
|
def initialize_for_key(key)
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
self.class.send :attr_accessor,
|
18
|
+
unique_key = unique_key(key)
|
19
|
+
|
20
|
+
return if @_unique_keys.include?(unique_key)
|
21
|
+
@_unique_keys << unique_key
|
22
|
+
instance_variable_set("@#{unique_key}", [])
|
23
|
+
self.class.send :attr_accessor, unique_key
|
19
24
|
end
|
20
25
|
|
21
26
|
def get(key)
|
22
27
|
initialize_for_key(key)
|
23
|
-
send(
|
28
|
+
send(unique_key(key))
|
24
29
|
end
|
25
30
|
|
26
31
|
def set(key, errors)
|
27
32
|
initialize_for_key(key)
|
28
|
-
send :"#{key
|
33
|
+
send :"#{unique_key(key)}=", Array.wrap(errors)
|
29
34
|
end
|
30
35
|
|
31
36
|
def add(key, error)
|
32
|
-
|
37
|
+
send(unique_key(key)) << error
|
33
38
|
end
|
34
39
|
|
35
40
|
def [](key)
|
@@ -40,14 +45,18 @@ module MotionPrime
|
|
40
45
|
set(key, errors)
|
41
46
|
end
|
42
47
|
|
48
|
+
def reset_for(key)
|
49
|
+
send :"#{unique_key(key)}=", []
|
50
|
+
end
|
51
|
+
|
43
52
|
def reset
|
44
|
-
@
|
45
|
-
|
53
|
+
@_unique_keys.each do |unique_key|
|
54
|
+
send :"#{unique_key}=", []
|
46
55
|
end
|
47
56
|
end
|
48
57
|
|
49
58
|
def messages
|
50
|
-
@
|
59
|
+
@_unique_keys.map{ |uniq_k| send(uniq_k) }.compact.flatten
|
51
60
|
end
|
52
61
|
|
53
62
|
def blank?
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module MotionPrime
|
2
2
|
module ModelFinderMethods
|
3
|
+
attr_accessor :bare_class
|
4
|
+
|
3
5
|
# Find all models
|
4
6
|
#
|
5
7
|
# @return [Array] array of models
|
@@ -141,7 +143,8 @@ module MotionPrime
|
|
141
143
|
end
|
142
144
|
|
143
145
|
def bare_class_name
|
144
|
-
self
|
146
|
+
subject = @bare_class || self
|
147
|
+
subject.to_s.split("::").last
|
145
148
|
end
|
146
149
|
|
147
150
|
private
|
@@ -28,8 +28,8 @@ module MotionPrime
|
|
28
28
|
def assign_attributes(new_attributes, options = {})
|
29
29
|
attributes = new_attributes.symbolize_keys
|
30
30
|
attributes.each do |k, v|
|
31
|
-
if
|
32
|
-
|
31
|
+
if has_attribute?(k)
|
32
|
+
assign_attribute(k, v) unless options[:skip_nil_values] && v.nil?
|
33
33
|
elsif options[:check_attribute_presence]
|
34
34
|
puts "unknown attribute: #{k}"
|
35
35
|
else
|
@@ -38,6 +38,14 @@ module MotionPrime
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
def assign_attribute(name, value)
|
42
|
+
self.send("#{name}=", value) if has_attribute?(name)
|
43
|
+
end
|
44
|
+
|
45
|
+
def has_attribute?(name)
|
46
|
+
respond_to?("#{name}=")
|
47
|
+
end
|
48
|
+
|
41
49
|
def attributes_hash
|
42
50
|
self.info.to_hash.symbolize_keys
|
43
51
|
end
|
@@ -51,7 +59,7 @@ module MotionPrime
|
|
51
59
|
end
|
52
60
|
|
53
61
|
def model_name
|
54
|
-
self.
|
62
|
+
self.class_name_without_kvo.underscore
|
55
63
|
end
|
56
64
|
|
57
65
|
def inspect
|
@@ -97,7 +105,7 @@ module MotionPrime
|
|
97
105
|
# end
|
98
106
|
#
|
99
107
|
# @return Nil
|
100
|
-
def attribute(name)
|
108
|
+
def attribute(name, options = {})
|
101
109
|
attributes << name
|
102
110
|
|
103
111
|
define_method(name) do |*args, &block|
|
@@ -105,7 +113,19 @@ module MotionPrime
|
|
105
113
|
end
|
106
114
|
|
107
115
|
define_method((name + "=").to_sym) do |*args, &block|
|
108
|
-
|
116
|
+
value = args[0]
|
117
|
+
case options[:type].to_s
|
118
|
+
when 'integer' then value = value.to_i
|
119
|
+
when 'float' then value = value.to_f
|
120
|
+
end unless value.nil?
|
121
|
+
|
122
|
+
self.info[name] = value
|
123
|
+
end
|
124
|
+
|
125
|
+
if options[:type].to_s == 'boolean'
|
126
|
+
define_method("#{name}?") do
|
127
|
+
!!self.info[name]
|
128
|
+
end
|
109
129
|
end
|
110
130
|
end
|
111
131
|
|
@@ -43,13 +43,7 @@ class NSFNanoStore
|
|
43
43
|
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
44
44
|
self
|
45
45
|
end
|
46
|
-
|
47
|
-
def +(object)
|
48
|
-
error_ptr = Pointer.new(:id)
|
49
|
-
self.addObject(object, error:error_ptr)
|
50
|
-
raise MotionPrime::StoreError, error_ptr[0].description if error_ptr[0]
|
51
|
-
self
|
52
|
-
end
|
46
|
+
alias_method :+, :<<
|
53
47
|
|
54
48
|
# delete a object or array of objects from the array
|
55
49
|
def delete(objects)
|
data/motion-prime/models/sync.rb
CHANGED
@@ -6,9 +6,9 @@ module MotionPrime
|
|
6
6
|
base.class_attribute :_associations
|
7
7
|
end
|
8
8
|
|
9
|
-
def sync_url(method = :get)
|
9
|
+
def sync_url(method = :get, options = {})
|
10
10
|
url = self.class.sync_url
|
11
|
-
url = url.call(method, self) if url.is_a?(Proc)
|
11
|
+
url = url.call(method, self, options) if url.is_a?(Proc)
|
12
12
|
normalize_sync_url(url)
|
13
13
|
end
|
14
14
|
|
@@ -38,12 +38,13 @@ module MotionPrime
|
|
38
38
|
should_fetch
|
39
39
|
end
|
40
40
|
|
41
|
-
method =
|
41
|
+
method = sync_options[:method]
|
42
|
+
method ||= if should_update
|
42
43
|
persisted? ? :put : :post
|
43
44
|
else
|
44
45
|
:get
|
45
46
|
end
|
46
|
-
url = sync_url(method)
|
47
|
+
url = sync_url(method, sync_options)
|
47
48
|
|
48
49
|
if url.blank?
|
49
50
|
should_fetch = false
|
@@ -53,9 +54,9 @@ module MotionPrime
|
|
53
54
|
should_fetch = !new_record? if should_fetch.nil?
|
54
55
|
should_update ||= new_record? unless should_fetch
|
55
56
|
|
56
|
-
fetch_with_url url do
|
57
|
+
fetch_with_url url do |data, status_code|
|
57
58
|
save if sync_options[:save]
|
58
|
-
block.call if use_callback
|
59
|
+
block.call(data, status_code) if use_callback
|
59
60
|
end if should_fetch
|
60
61
|
|
61
62
|
update_with_url url, sync_options do |data, status_code|
|
@@ -64,38 +65,50 @@ module MotionPrime
|
|
64
65
|
block.call(data, status_code) if use_callback && !should_fetch
|
65
66
|
end if should_update
|
66
67
|
|
67
|
-
fetch_associations(sync_options) do
|
68
|
+
fetch_associations(sync_options) do |data, status_code|
|
68
69
|
# run callback only if it wasn't run on fetch or update
|
69
|
-
block.call if use_callback && !should_fetch && !should_update
|
70
|
+
block.call(data, status_code) if use_callback && !should_fetch && !should_update
|
70
71
|
end if should_fetch_associations
|
71
72
|
end
|
72
73
|
|
73
74
|
# fetch from server using url
|
74
75
|
def fetch_with_url(url, &block)
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
76
|
+
use_callback = block_given?
|
77
|
+
api_client.get(url) do |data, status_code|
|
78
|
+
fetch_with_attributes(data, &block) if data.present?
|
79
|
+
block.call(data, status_code) if use_callback
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
82
83
|
# update on server using url
|
83
84
|
def update_with_url(url, sync_options = nil, &block)
|
84
85
|
use_callback = block_given?
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
86
|
+
filtered_attributes = filtered_updatable_attributes(sync_options)
|
87
|
+
|
88
|
+
post_data = sync_options[:params_root] || {}
|
89
|
+
post_data[:files] = {}
|
90
|
+
filtered_attributes.delete(:files).each do |file_name, file|
|
91
|
+
post_data[:files][[model_name, file_name].join] = file
|
92
|
+
end
|
93
|
+
post_data[model_name] = filtered_attributes
|
94
|
+
|
95
|
+
method = sync_options[:method] || (id ? :put : :post)
|
96
|
+
api_client.send(method, url, post_data) do |data, status_code|
|
97
|
+
update_from_response = sync_options.has_key?(:update_from_response) ? sync_options[:update_from_response] : true
|
98
|
+
if update_from_response && status_code.to_s =~ /20\d/ && data.is_a?(Hash)
|
99
|
+
set_attributes_from_response(data)
|
92
100
|
end
|
93
101
|
block.call(data, status_code) if use_callback
|
94
102
|
end
|
95
103
|
end
|
96
104
|
|
105
|
+
def set_attributes_from_response(data)
|
106
|
+
self.id ||= data.delete('id')
|
107
|
+
fetch_with_attributes(data)
|
108
|
+
end
|
109
|
+
|
97
110
|
# set attributes, using fetch
|
98
|
-
def fetch_with_attributes(attrs
|
111
|
+
def fetch_with_attributes(attrs)
|
99
112
|
attrs.each do |key, value|
|
100
113
|
if respond_to?(:"fetch_#{key}")
|
101
114
|
self.send(:"fetch_#{key}", value)
|
@@ -103,14 +116,14 @@ module MotionPrime
|
|
103
116
|
self.send(:"#{key}=", value)
|
104
117
|
end
|
105
118
|
end
|
106
|
-
block.call(self) if block_given?
|
107
119
|
end
|
108
120
|
|
109
121
|
def fetch_associations(sync_options = {}, &block)
|
110
122
|
use_callback = block_given?
|
111
123
|
associations = self.class._associations || {}
|
124
|
+
association_keys = associations.keys.select { |key| fetch_association?(key) }
|
112
125
|
|
113
|
-
|
126
|
+
association_keys.each_with_index do |key, index|
|
114
127
|
if use_callback && associations.count - 1 == index
|
115
128
|
fetch_association(key, sync_options, &block)
|
116
129
|
else
|
@@ -119,21 +132,30 @@ module MotionPrime
|
|
119
132
|
end
|
120
133
|
end
|
121
134
|
|
135
|
+
def fetch_association?(key)
|
136
|
+
options = self.class._associations[key]
|
137
|
+
return if options[:if] && !options[:if].to_proc.call(self)
|
138
|
+
options[:sync_url].present?
|
139
|
+
end
|
140
|
+
|
122
141
|
def fetch_association(key, sync_options = {}, &block)
|
142
|
+
return unless fetch_association?(key)
|
123
143
|
options = self.class._associations[key]
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
144
|
+
if options[:type] == :many
|
145
|
+
fetch_has_many(key, options, sync_options, &block)
|
146
|
+
else
|
147
|
+
fetch_has_one(key, options, sync_options, &block)
|
148
|
+
end
|
128
149
|
end
|
129
150
|
|
130
151
|
def fetch_has_many(key, options = {}, sync_options = {}, &block)
|
131
152
|
old_collection = self.send(key)
|
153
|
+
|
132
154
|
use_callback = block_given?
|
133
|
-
puts "SYNC: started sync for #{key} in #{self.
|
134
|
-
api_client.get normalize_sync_url(options[:sync_url]) do |data|
|
155
|
+
puts "SYNC: started sync for #{key} in #{self.class_name_without_kvo}"
|
156
|
+
api_client.get normalize_sync_url(options[:sync_url]) do |data, status_code|
|
135
157
|
data = data[options[:sync_key]] if options[:sync_key]
|
136
|
-
if data
|
158
|
+
if data
|
137
159
|
# Update/Create existing records
|
138
160
|
data.each do |attributes|
|
139
161
|
model = old_collection.detect{ |model| model.id == attributes[:id]}
|
@@ -151,19 +173,19 @@ module MotionPrime
|
|
151
173
|
end
|
152
174
|
end
|
153
175
|
save if sync_options[:save]
|
154
|
-
puts "SYNC: finished sync for #{key} in #{self.
|
155
|
-
block.call if use_callback
|
176
|
+
puts "SYNC: finished sync for #{key} in #{self.class_name_without_kvo}"
|
177
|
+
block.call(data, status_code) if use_callback
|
156
178
|
else
|
157
|
-
puts "SYNC ERROR: failed sync for #{key} in #{self.
|
158
|
-
block.call if use_callback
|
179
|
+
puts "SYNC ERROR: failed sync for #{key} in #{self.class_name_without_kvo}"
|
180
|
+
block.call(data, status_code) if use_callback
|
159
181
|
end
|
160
182
|
end
|
161
183
|
end
|
162
184
|
|
163
185
|
def fetch_has_one(key, options = {}, &block)
|
164
186
|
use_callback = block_given?
|
165
|
-
puts "SYNC: started sync for #{key} in #{self.
|
166
|
-
api_client.get normalize_sync_url(options[:sync_url]) do |data|
|
187
|
+
puts "SYNC: started sync for #{key} in #{self.class_name_without_kvo}"
|
188
|
+
api_client.get normalize_sync_url(options[:sync_url]) do |data, status_code|
|
167
189
|
data = data[options[:sync_key]] if options[:sync_key]
|
168
190
|
if data.present?
|
169
191
|
model = self.send(key)
|
@@ -173,10 +195,10 @@ module MotionPrime
|
|
173
195
|
end
|
174
196
|
model.fetch_with_attributes(data)
|
175
197
|
model.save if sync_options[:save]
|
176
|
-
block.call if use_callback
|
198
|
+
block.call(data, status_code) if use_callback
|
177
199
|
else
|
178
|
-
puts "SYNC ERROR: failed sync for #{key} in #{self.
|
179
|
-
block.call if use_callback
|
200
|
+
puts "SYNC ERROR: failed sync for #{key} in #{self.class_name_without_kvo}"
|
201
|
+
block.call(data, status_code) if use_callback
|
180
202
|
end
|
181
203
|
end
|
182
204
|
end
|
@@ -186,19 +208,29 @@ module MotionPrime
|
|
186
208
|
updatable_attributes = self.class.updatable_attributes
|
187
209
|
|
188
210
|
if updatable_attributes.blank?
|
189
|
-
|
211
|
+
attrs = slice_attributes ? attributes_hash.slice(*slice_attributes) : attributes_hash
|
212
|
+
return attrs.merge(files: {})
|
190
213
|
end
|
191
214
|
|
192
215
|
updatable_attributes = updatable_attributes.slice(*slice_attributes) if slice_attributes
|
193
|
-
updatable_attributes.to_a.inject({}) do |hash, attribute|
|
216
|
+
updatable_attributes.to_a.inject({files: {}}) do |hash, attribute|
|
194
217
|
key, options = *attribute
|
195
|
-
|
218
|
+
next hash if options[:if] && !send(options[:if])
|
196
219
|
value = if block = options[:block]
|
197
|
-
block.call(self)
|
220
|
+
block.call(self, hash)
|
198
221
|
else
|
199
222
|
info[key]
|
200
223
|
end
|
201
|
-
|
224
|
+
|
225
|
+
if key.to_s.starts_with?('file_')
|
226
|
+
value.to_a.each do |file_data|
|
227
|
+
file_name, file = file_data.to_a
|
228
|
+
hash[:files]["[#{key.partition('_').last}]#{file_name}"] = file
|
229
|
+
end
|
230
|
+
else
|
231
|
+
hash.merge!(key => value)
|
232
|
+
end
|
233
|
+
hash
|
202
234
|
end
|
203
235
|
end
|
204
236
|
|