medic 0.0.2 → 0.1.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.
Files changed (41) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +4 -4
  3. data/lib/medic/{anchored_object_query.rb → anchored_object_query_builder.rb} +5 -2
  4. data/lib/medic/{correlation_query.rb → correlation_query_builder.rb} +5 -2
  5. data/lib/medic/finders.rb +22 -17
  6. data/lib/medic/interval.rb +1 -0
  7. data/lib/medic/{observer_query.rb → observer_query_builder.rb} +5 -2
  8. data/lib/medic/predicate.rb +1 -1
  9. data/lib/medic/query_options.rb +1 -1
  10. data/lib/medic/{sample_query.rb → sample_query_builder.rb} +6 -2
  11. data/lib/medic/{source_query.rb → source_query_builder.rb} +5 -2
  12. data/lib/medic/statistics_collection_query_builder.rb +45 -0
  13. data/lib/medic/{statistics_query.rb → statistics_query_builder.rb} +5 -2
  14. data/lib/medic/store.rb +52 -18
  15. data/lib/medic/units.rb +15 -0
  16. data/lib/medic/version.rb +1 -1
  17. data/spec/medic/anchor.rb +1 -1
  18. data/spec/medic/anchored_object_query_builder_spec.rb +12 -0
  19. data/spec/medic/{correlation_query_spec.rb → correlation_query_builder_spec.rb} +4 -4
  20. data/spec/medic/hk_constants_spec.rb +1 -1
  21. data/spec/medic/interval_spec.rb +1 -1
  22. data/spec/medic/medic_spec.rb +1 -1
  23. data/spec/medic/observer_query_builder_spec.rb +12 -0
  24. data/spec/medic/predicate_spec.rb +1 -1
  25. data/spec/medic/query_options_spec.rb +1 -1
  26. data/spec/medic/sample_query_builder_spec.rb +12 -0
  27. data/spec/medic/sort_spec.rb +1 -1
  28. data/spec/medic/source_query_builder_spec.rb +12 -0
  29. data/spec/medic/statistics_collection_query_builder_spec.rb +56 -0
  30. data/spec/medic/statistics_options_spec.rb +1 -1
  31. data/spec/medic/statistics_query_builder_spec.rb +12 -0
  32. data/spec/medic/store_spec.rb +16 -15
  33. data/spec/medic/types_spec.rb +1 -1
  34. metadata +25 -24
  35. data/lib/medic/statistics_collection_query.rb +0 -39
  36. data/spec/medic/anchored_object_query_spec.rb +0 -12
  37. data/spec/medic/observer_query_spec.rb +0 -12
  38. data/spec/medic/sample_query_spec.rb +0 -12
  39. data/spec/medic/source_query_spec.rb +0 -12
  40. data/spec/medic/statistics_collection_query_spec.rb +0 -27
  41. data/spec/medic/statistics_query_spec.rb +0 -12
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: bf3a75beba5a3f3be3df75476d6d18d188752bac
4
- data.tar.gz: 01bb258ba550c735090e7d04df792972562f4f91
3
+ metadata.gz: 885ef7d6a312a5644cf27850d9bb01fc24e5bcaa
4
+ data.tar.gz: 41f408b021b7b03bcab32b2eca082274439b7c9e
5
5
  SHA512:
6
- metadata.gz: 02ff5adbb1f076e1e95fee777d4d5289e0bd1eb73808f32d3ee90a6b2a45aafc27b13e323ea96885e55294e4356d2eb783cbd02e7b271287a7dc1afa07df7fa1
7
- data.tar.gz: 780718864993970ea3889ac42df1627066152d3862aab9be21f7f5eded7b146195874fff3c1a68497dc46b14482aa5348f089c70eac31e9572250511ee34ca8e
6
+ metadata.gz: 1a6b3e8f52c4338cbb9de50165fde57c559f41136e141776a9794544bbbd37bf005d156ef84482150f4d253b7f22dc06b3e883917bae28df256296fc43d9568b
7
+ data.tar.gz: f3372641785e97bf22028ec8a90c22a9bb6f2f1fffe076fed282e96beda379d55a3a3929be7e8c77647cecfda8383b399d00e8f15d1a52bae2801dc53b270c6f
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # Medic [![Gem Version](https://badge.fury.io/rb/medic.svg)](http://badge.fury.io/rb/medic) [![Build Status](https://travis-ci.org/ryanlntn/medic.svg)](https://travis-ci.org/ryanlntn/medic) [![Code Climate](https://codeclimate.com/github/ryanlntn/medic/badges/gpa.svg)](https://codeclimate.com/github/ryanlntn/medic) [![Dependency Status](https://gemnasium.com/ryanlntn/medic.svg)](https://gemnasium.com/ryanlntn/medic)
2
2
 
3
- Is HealthKit's verbose and convoluted API driving you to autolobotomization? Quick! You need a medic!
3
+ Is HealthKit's verbose and convoluted API driving you mad? Quick! You need a medic!
4
4
 
5
5
  ## Installation
6
6
 
@@ -202,12 +202,12 @@ Medic.blood_type # => :o_negative
202
202
 
203
203
  #### Queries
204
204
 
205
- If for some reason you need to access the `HKSample` objects directly you can use Medic's Query objects:
205
+ If for some reason you need to access the `HKSample` objects directly you can use Medic's QueryBuilder objects:
206
206
 
207
207
  ```ruby
208
208
  query_params = { type: :dietary_protein, sort_desc: :start_date, limit: 7 }
209
209
 
210
- query = Medic::SampleQuery.new query_params do |query, results, error|
210
+ query = Medic::SampleQueryBuilder.new query_params do |query, results, error|
211
211
  if results
212
212
  results.each do |sample|
213
213
  NSLog "#{sample.startDate} - #{sample.quantity.doubleValueForUnit(HKUnit.gramUnit)}"
@@ -215,7 +215,7 @@ query = Medic::SampleQuery.new query_params do |query, results, error|
215
215
  else
216
216
  NSLog "no results"
217
217
  end
218
- end
218
+ end.query
219
219
 
220
220
  Medic.execute(query)
221
221
  ```
@@ -1,12 +1,15 @@
1
1
  module Medic
2
- class AnchoredObjectQuery < HKAnchoredObjectQuery
2
+ class AnchoredObjectQueryBuilder
3
+ attr_reader :params
4
+ attr_reader :query
3
5
 
4
6
  include Medic::Types
5
7
  include Medic::Predicate
6
8
  include Medic::Anchor
7
9
 
8
10
  def initialize(args={}, block=Proc.new)
9
- self.initWithType(object_type(args[:type]),
11
+ @params = args
12
+ @query = HKAnchoredObjectQuery.alloc.initWithType(object_type(args[:type]),
10
13
  predicate: predicate(args),
11
14
  anchor: anchor_for_symbol(args[:anchor_date] || args[:anchor] || args[:date] || HKAnchoredObjectQueryNoAnchor),
12
15
  limit: args[:limit] || HKObjectQueryNoLimit,
@@ -1,11 +1,14 @@
1
1
  module Medic
2
- class CorrelationQuery < HKCorrelationQuery
2
+ class CorrelationQueryBuilder
3
+ attr_reader :params
4
+ attr_reader :query
3
5
 
4
6
  include Medic::Types
5
7
  include Medic::Predicate
6
8
 
7
9
  def initialize(args={}, block=Proc.new)
8
- self.initWithType(object_type(args[:type]),
10
+ @params = args
11
+ @query = HKCorrelationQuery.alloc.initWithType(object_type(args[:type]),
9
12
  predicate: predicate(args),
10
13
  samplePredicates: sample_predicates(args[:sample_predicates]),
11
14
  completion: block
data/lib/medic/finders.rb CHANGED
@@ -3,62 +3,67 @@ module Medic
3
3
 
4
4
  def observe(type, options={}, block=Proc.new)
5
5
  query_params = options.merge(type: type)
6
- query = Medic::ObserverQuery.new query_params do |query, completion, error|
6
+ query = Medic::ObserverQueryBuilder.new query_params do |query, completion, error|
7
7
  block.call(completion, error)
8
- end
8
+ end.query
9
9
  Medic.execute(query)
10
10
  end
11
11
 
12
12
  def find_sources(type, options={}, block=Proc.new)
13
13
  query_params = options.merge(type: type)
14
- query = Medic::SourceQuery.new query_params do |query, results, error|
14
+ query = Medic::SourceQueryBuilder.new query_params do |query, results, error|
15
15
  sources = results ? results.allObjects.map{ |source| source.name.to_s } : []
16
16
  block.call(sources)
17
- end
17
+ end.query
18
18
  Medic.execute(query)
19
19
  end
20
20
 
21
21
  def find_samples(type, options={}, block=Proc.new)
22
22
  query_params = options.merge(type: type)
23
- query = Medic::SampleQuery.new query_params do |query, results, error|
23
+ query = Medic::SampleQueryBuilder.new query_params do |query, results, error|
24
24
  block.call(samples_to_hashes(Array(results)))
25
- end
25
+ end.query
26
26
  Medic.execute(query)
27
27
  end
28
28
 
29
29
  def find_correlations(type, options={}, block=Proc.new)
30
30
  query_params = options.merge(type: type)
31
- query = Medic::CorrelationQuery.new query_params do |query, correlations, error|
31
+ query = Medic::CorrelationQueryBuilder.new query_params do |query, correlations, error|
32
32
  block.call(samples_to_hashes(Array(correlations)))
33
- end
33
+ end.query
34
34
  Medic.execute(query)
35
35
  end
36
36
 
37
37
  def find_anchored(type, options={}, block=Proc.new)
38
38
  query_params = options.merge(type: type)
39
- query = Medic::AnchoredObjectQuery.new query_params do |query, results, new_anchor, error|
39
+ query = Medic::AnchoredObjectQueryBuilder.new query_params do |query, results, new_anchor, error|
40
40
  block.call(samples_to_hashes(Array(results)), new_anchor)
41
- end
41
+ end.query
42
42
  Medic.execute(query)
43
43
  end
44
44
 
45
45
  def find_statistics(type, options={}, block=Proc.new)
46
46
  query_params = options.merge(type: type)
47
- query = Medic::StatisticsQuery.new query_params do |query, statistics, error|
47
+ query = Medic::StatisticsQueryBuilder.new query_params do |query, statistics, error|
48
48
  block.call(statistics_to_hash(statistics)) if statistics
49
- end
49
+ end.query
50
50
  Medic.execute(query)
51
51
  end
52
52
 
53
53
  def find_statistics_collection(type, options={}, block=Proc.new)
54
54
  query_params = options.merge(type: type)
55
- query = Medic::StatisticsCollectionQuery.new query_params do |query, collection, error|
55
+ query = Medic::StatisticsCollectionQueryBuilder.new query_params do |query, collection, error|
56
+ from_date = options[:from_date] || options[:from] || options[:start_date] || collection.anchorDate
57
+ to_date = options[:to_date] || options[:to] || options[:end_date] || NSDate.date
56
58
  formatted_stats = []
57
- collection.enumerateStatisticsFromDate(collection.anchorDate, toDate: NSDate.date, withBlock: ->(result, stop){
58
- formatted_stats << statistics_to_hash(result)
59
- })
59
+ if collection
60
+ collection.enumerateStatisticsFromDate(from_date, toDate: to_date, withBlock: ->(result, stop){
61
+ formatted_stats << statistics_to_hash(result)
62
+ })
63
+ end
60
64
  block.call(formatted_stats)
61
- end
65
+ end.query
66
+
62
67
  Medic.execute(query)
63
68
  end
64
69
 
@@ -22,6 +22,7 @@ module Medic
22
22
  end
23
23
  end
24
24
  n ||= 1
25
+
25
26
  NSDateComponents.new.send("#{component}=", n)
26
27
  end
27
28
 
@@ -1,11 +1,14 @@
1
1
  module Medic
2
- class ObserverQuery < HKObserverQuery
2
+ class ObserverQueryBuilder
3
+ attr_reader :params
4
+ attr_reader :query
3
5
 
4
6
  include Medic::Types
5
7
  include Medic::Predicate
6
8
 
7
9
  def initialize(args={}, block=Proc.new)
8
- self.initWithSampleType(object_type(args[:type]),
10
+ @params = args
11
+ @query = HKObserverQuery.alloc.initWithSampleType(object_type(args[:type]),
9
12
  predicate: predicate(args),
10
13
  updateHandler: block
11
14
  )
@@ -23,7 +23,7 @@ module Medic
23
23
  elsif args[:no_correlation]
24
24
  HKQuery.predicateForObjectsWithNoCorrelation
25
25
  elsif args[:start_date] && args[:end_date]
26
- options = query_options(args[:options]) || HKQueryOptionNone
26
+ options = query_options(args[:query_options]) || HKQueryOptionNone
27
27
  HKQuery.predicateForSamplesWithStartDate(args[:start_date], endDate: args[:end_date], options: options)
28
28
  elsif args[:workout]
29
29
  HKQuery.predicateForObjectsFromWorkout(args[:workout])
@@ -10,7 +10,7 @@ module Medic
10
10
  def query_options(symbols)
11
11
  options = 0
12
12
  Array(symbols).each do |option|
13
- options = options | query_option(option)
13
+ options |= query_option(option)
14
14
  end
15
15
  options
16
16
  end
@@ -1,16 +1,20 @@
1
1
  module Medic
2
- class SampleQuery < HKSampleQuery
2
+ class SampleQueryBuilder
3
+ attr_reader :params
4
+ attr_reader :query
3
5
 
4
6
  include Medic::Types
5
7
  include Medic::Predicate
6
8
  include Medic::Sort
7
9
 
8
10
  def initialize(args={}, block=Proc.new)
11
+ @params = args
12
+
9
13
  sort = args[:sort_descriptors] || args[:sort_by] || args[:sort_asc] || args[:sort]
10
14
  sort = sort_descriptors(sort) if sort
11
15
  sort ||= sort_descriptors(args[:sort_desc], false) if args[:sort_desc]
12
16
 
13
- self.initWithSampleType(object_type(args[:type]),
17
+ @query = HKSampleQuery.alloc.initWithSampleType(object_type(args[:type]),
14
18
  predicate: predicate(args),
15
19
  limit: args[:limit] || HKObjectQueryNoLimit,
16
20
  sortDescriptors: sort,
@@ -1,11 +1,14 @@
1
1
  module Medic
2
- class SourceQuery < HKSourceQuery
2
+ class SourceQueryBuilder
3
+ attr_reader :params
4
+ attr_reader :query
3
5
 
4
6
  include Medic::Types
5
7
  include Medic::Predicate
6
8
 
7
9
  def initialize(args={}, block=Proc.new)
8
- self.initWithSampleType(object_type(args[:type]),
10
+ @params = args
11
+ @query = HKSourceQuery.alloc.initWithSampleType(object_type(args[:type]),
9
12
  samplePredicate: predicate(args),
10
13
  completionHandler: block
11
14
  )
@@ -0,0 +1,45 @@
1
+ module Medic
2
+ class StatisticsCollectionQueryBuilder
3
+ attr_reader :params
4
+ attr_reader :query
5
+
6
+ include Medic::Types
7
+ include Medic::Predicate
8
+ include Medic::StatisticsOptions
9
+ include Medic::Anchor
10
+ include Medic::Interval
11
+
12
+ def initialize(args={})
13
+ @params = args
14
+ @query = HKStatisticsCollectionQuery.alloc.initWithQuantityType(object_type(args[:type]),
15
+ quantitySamplePredicate: predicate(args),
16
+ options: options_for_stat_query(args[:options]),
17
+ anchorDate: anchor_for_symbol(args[:anchor_date] || args[:anchor] || args[:date] || NSDate.date),
18
+ intervalComponents: interval(args[:interval_components] || args[:interval])
19
+ )
20
+ if block_given?
21
+ handler = Proc.new
22
+ @query.initialResultsHandler = handler
23
+ @query.statisticsUpdateHandler = Proc.new{|q,_,r,e| handler.call(q,r,e)} if args[:update] == true
24
+ end
25
+ @query.statisticsUpdateHandler = args[:update] if args[:update].is_a?(Proc)
26
+ end
27
+
28
+ def initial_results_handler
29
+ @query.initialResultsHandler
30
+ end
31
+
32
+ def initial_results_handler=(callback=Proc.new)
33
+ @query.initialResultsHandler = callback
34
+ end
35
+
36
+ def statistics_update_handler
37
+ @query.statisticsUpdateHandler
38
+ end
39
+
40
+ def statistics_update_handler=(callback=Proc.new)
41
+ @query.statisticsUpdateHandler = callback
42
+ end
43
+
44
+ end
45
+ end
@@ -1,12 +1,15 @@
1
1
  module Medic
2
- class StatisticsQuery < HKStatisticsQuery
2
+ class StatisticsQueryBuilder
3
+ attr_reader :params
4
+ attr_reader :query
3
5
 
4
6
  include Medic::Types
5
7
  include Medic::Predicate
6
8
  include Medic::StatisticsOptions
7
9
 
8
10
  def initialize(args={}, block=Proc.new)
9
- self.initWithQuantityType(object_type(args[:type]),
11
+ @params = args
12
+ @query = HKStatisticsQuery.alloc.initWithQuantityType(object_type(args[:type]),
10
13
  quantitySamplePredicate: predicate(args),
11
14
  options: options_for_stat_query(args[:options]),
12
15
  completionHandler: block
data/lib/medic/store.rb CHANGED
@@ -1,20 +1,26 @@
1
1
  module Medic
2
- class Store < HKHealthStore
3
-
2
+ class Store
4
3
  include Medic::Types
4
+ include Medic::Units
5
5
  include Medic::HKConstants
6
6
 
7
7
  def self.shared
8
- Dispatch.once { @store ||= new }
9
- @store
8
+ Dispatch.once { @@hk_store ||= HKHealthStore.new }
9
+ Dispatch.once { @medic_store ||= new }
10
+ @medic_store
11
+ end
12
+
13
+ def self.hk_store
14
+ @@hk_store
10
15
  end
11
16
 
12
17
  def self.unload
13
- @store = nil
18
+ @@hk_store = nil
19
+ @medic_store = nil
14
20
  end
15
21
 
16
22
  def self.available?
17
- isHealthDataAvailable
23
+ HKHealthStore.isHealthDataAvailable
18
24
  end
19
25
  singleton_class.send(:alias_method, :is_available?, :available?)
20
26
 
@@ -22,13 +28,13 @@ module Medic
22
28
  share = Array(types[:share] || types[:write]).map{ |sym| object_type(sym) }
23
29
  read = Array(types[:read]).map{ |sym| object_type(sym) }
24
30
 
25
- requestAuthorizationToShareTypes(NSSet.setWithArray(share), readTypes: NSSet.setWithArray(read), completion: ->(success, error){
31
+ @@hk_store.requestAuthorizationToShareTypes(NSSet.setWithArray(share), readTypes: NSSet.setWithArray(read), completion: ->(success, error){
26
32
  block.call(success, error)
27
33
  })
28
34
  end
29
35
 
30
36
  def authorized?(sym)
31
- authorizationStatusForType(object_type(sym)) == HKAuthorizationStatusSharingAuthorized
37
+ @@hk_store.authorizationStatusForType(object_type(sym)) == HKAuthorizationStatusSharingAuthorized
32
38
  end
33
39
  alias_method :authorized_for?, :authorized?
34
40
  alias_method :is_authorized?, :authorized?
@@ -36,7 +42,7 @@ module Medic
36
42
 
37
43
  def biological_sex
38
44
  error = Pointer.new(:object)
39
- sex = biologicalSexWithError error
45
+ sex = @@hk_store.biologicalSexWithError error
40
46
  if block_given?
41
47
  yield BIOLOGICAL_SEXES.invert[sex.biologicalSex], error[0]
42
48
  else
@@ -46,7 +52,7 @@ module Medic
46
52
 
47
53
  def blood_type
48
54
  error = Pointer.new(:object)
49
- blood = bloodTypeWithError error
55
+ blood = @@hk_store.bloodTypeWithError error
50
56
  if block_given?
51
57
  yield BLOOD_TYPES.invert[blood.bloodType], error[0]
52
58
  else
@@ -56,7 +62,7 @@ module Medic
56
62
 
57
63
  def date_of_birth
58
64
  error = Pointer.new(:object)
59
- birthday = dateOfBirthWithError error
65
+ birthday = @@hk_store.dateOfBirthWithError error
60
66
  if block_given?
61
67
  yield birthday, error[0]
62
68
  else
@@ -65,14 +71,15 @@ module Medic
65
71
  end
66
72
 
67
73
  def delete(hk_object, block=Proc.new)
68
- deleteObject(hk_object, withCompletion: ->(success, error){
74
+ @@hk_store.deleteObject(hk_object, withCompletion: ->(success, error){
69
75
  block.call(success, error)
70
76
  })
71
77
  end
72
78
  alias_method :delete_object, :delete
73
79
 
74
80
  def save(hk_objects, block=Proc.new)
75
- saveObjects(Array(hk_objects), withCompletion: ->(success, error){
81
+ objs_array = hk_objects.is_a?(Array) ? hk_objects : [hk_objects]
82
+ @@hk_store.saveObjects(objs_array.map{|obj| prepare_for_save(obj)}, withCompletion: ->(success, error){
76
83
  block.call(success, error)
77
84
  })
78
85
  end
@@ -83,17 +90,17 @@ module Medic
83
90
  # addSamples:toWorkout:completion:
84
91
 
85
92
  def execute(query)
86
- executeQuery(query)
93
+ @@hk_store.executeQuery(query)
87
94
  end
88
95
  alias_method :execute_query, :execute
89
96
 
90
97
  def stop(query)
91
- stopQuery(query)
98
+ @@hk_store.stopQuery(query)
92
99
  end
93
100
  alias_method :stop_query, :stop
94
101
 
95
102
  def enable_background_delivery(type, frequency, block=Proc.new)
96
- enableBackgroundDeliveryForType(object_type(type), frequency: update_frequency(frequency), withCompletion: ->(success, error){
103
+ @@hk_store.enableBackgroundDeliveryForType(object_type(type), frequency: update_frequency(frequency), withCompletion: ->(success, error){
97
104
  block.call(success, error)
98
105
  })
99
106
  end
@@ -101,17 +108,44 @@ module Medic
101
108
 
102
109
  def disable_background_delivery(type, block=Proc.new)
103
110
  return disable_all_background_delivery(block) if type == :all
104
- disableBackgroundDeliveryForType(object_type(type), withCompletion: ->(success, error){
111
+ @@hk_store.disableBackgroundDeliveryForType(object_type(type), withCompletion: ->(success, error){
105
112
  block.call(success, error)
106
113
  })
107
114
  end
108
115
  alias_method :disable_background_delivery_for, :disable_background_delivery
109
116
 
110
117
  def disable_all_background_delivery(block=Proc.new)
111
- disableAllBackgroundDeliveryWithCompletion(->(success, error){
118
+ @@hk_store.disableAllBackgroundDeliveryWithCompletion(->(success, error){
112
119
  block.call(success, error)
113
120
  })
114
121
  end
115
122
 
123
+ private
124
+
125
+ def prepare_for_save(sample)
126
+ return sample if sample.kind_of? HKSample
127
+
128
+ date = sample[:date] || NSDate.date
129
+ start_date = sample[:start] || sample[:start_date] || date
130
+ end_date = sample[:end] || sample[:end_date] || date
131
+ metadata = sample[:metadata] || {}
132
+
133
+ type = object_type(sample[:type] || sample[:sample_type] || sample[:quantity_type] || sample[:correlation_type] || sample[:category_type])
134
+
135
+ case type
136
+ when HKQuantityType
137
+ quantity = HKQuantity.quantityWithUnit((sample_unit(sample[:unit]) || type.canonicalUnit), doubleValue: sample[:quantity])
138
+ HKQuantitySample.quantitySampleWithType(type, quantity: quantity, startDate: start_date, endDate: end_date, metadata: metadata)
139
+ when HKCorrelationType
140
+ objects = (sample[:objects].is_a?(Array) ? sample[:objects] : [sample[:objects]]).map{|obj| prepare_for_save(obj)}
141
+ HKCorrelation.correlationWithType(type, startDate: start_date, endDate: end_date, objects: objects, metadata: metadata)
142
+ when HKCategoryType
143
+ value = sleep_analysis(sample[:value]) # SleepAnalysis is the only category type at the moment
144
+ HKCategorySample.categorySampleWithType(type, value: value, startDate: start_date, endDate: end_date, metadata: metadata)
145
+ else
146
+ # handle workouts
147
+ end
148
+ end
149
+
116
150
  end
117
151
  end
@@ -0,0 +1,15 @@
1
+ module Medic
2
+ module Units
3
+
4
+ def sample_unit(u)
5
+ return unless u
6
+ camelized = u.to_s.gsub(/_([a-z]*)/){ "#{$1.capitalize}" }
7
+ if HKUnit.respond_to?(:"#{camelized}Unit")
8
+ HKUnit.send(:"#{camelized}Unit")
9
+ else
10
+ HKUnit.unitFromString(u.to_s)
11
+ end
12
+ end
13
+
14
+ end
15
+ end
data/lib/medic/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Medic
2
- VERSION = "0.0.2"
2
+ VERSION = "0.1.0"
3
3
  end
data/spec/medic/anchor.rb CHANGED
@@ -1,4 +1,4 @@
1
- describe "Medic::Anchor" do
1
+ describe Medic::Anchor do
2
2
 
3
3
  before do
4
4
  @subject = Object.new
@@ -0,0 +1,12 @@
1
+ describe Medic::AnchoredObjectQueryBuilder do
2
+
3
+ before do
4
+ @subject = Medic::AnchoredObjectQueryBuilder.new type: :step_count do |query, results, new_anchor, error|
5
+ end
6
+ end
7
+
8
+ it "has a query getter that returns an HKAnchoredObjectQuery" do
9
+ @subject.query.should.be.kind_of? HKAnchoredObjectQuery
10
+ end
11
+
12
+ end
@@ -1,16 +1,16 @@
1
- describe "Medic::CorrelationQuery" do
1
+ describe Medic::CorrelationQueryBuilder do
2
2
 
3
3
  before do
4
4
  high_cal = HKQuantity.quantityWithUnit(HKUnit.kilocalorieUnit, doubleValue: 800.0)
5
5
  greater_than_high_cal = HKQuery.predicateForQuantitySamplesWithOperatorType(NSGreaterThanOrEqualToPredicateOperatorType, quantity: high_cal)
6
6
  energy_consumed = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierDietaryEnergyConsumed)
7
7
  sample_predicates = { energy_consumed => greater_than_high_cal }
8
- @subject = Medic::CorrelationQuery.new type: :food, sample_predicates: sample_predicates do |query, correlations, error|
8
+ @subject = Medic::CorrelationQueryBuilder.new type: :food, sample_predicates: sample_predicates do |query, correlations, error|
9
9
  end
10
10
  end
11
11
 
12
- it "is a subclass of HKCorrelationQuery" do
13
- @subject.should.be.kind_of? HKCorrelationQuery
12
+ it "has a query getter that returns an HKCorrelationQuery" do
13
+ @subject.query.should.be.kind_of? HKCorrelationQuery
14
14
  end
15
15
 
16
16
  end
@@ -1,4 +1,4 @@
1
- describe "Medic::HKConstants" do
1
+ describe Medic::HKConstants do
2
2
 
3
3
  before do
4
4
  @subject = Object.new
@@ -1,4 +1,4 @@
1
- describe "Medic::Interval" do
1
+ describe Medic::Interval do
2
2
 
3
3
  before do
4
4
  @subject = Object.new
@@ -1,4 +1,4 @@
1
- describe "Medic" do
1
+ describe Medic do
2
2
 
3
3
  before do
4
4
  @store = Medic::Store.shared
@@ -0,0 +1,12 @@
1
+ describe Medic::ObserverQueryBuilder do
2
+
3
+ before do
4
+ @subject = Medic::ObserverQueryBuilder.new type: :step_count do |query, completion, error|
5
+ end
6
+ end
7
+
8
+ it "has a query getter that returns an HKObserverQuery" do
9
+ @subject.query.should.be.kind_of? HKObserverQuery
10
+ end
11
+
12
+ end
@@ -1,4 +1,4 @@
1
- describe "Medic::Predicate" do
1
+ describe Medic::Predicate do
2
2
 
3
3
  before do
4
4
  @subject = Object.new
@@ -1,4 +1,4 @@
1
- describe "Medic::QueryOptions" do
1
+ describe Medic::QueryOptions do
2
2
 
3
3
  before do
4
4
  @subject = Object.new
@@ -0,0 +1,12 @@
1
+ describe Medic::SampleQueryBuilder do
2
+
3
+ before do
4
+ @subject = Medic::SampleQueryBuilder.new type: :dietary_protein, limit: 7 do |query, results, error|
5
+ end
6
+ end
7
+
8
+ it "has a query getter that returns an HKSampleQuery" do
9
+ @subject.query.should.be.kind_of? HKSampleQuery
10
+ end
11
+
12
+ end
@@ -1,4 +1,4 @@
1
- describe "Medic::Sort" do
1
+ describe Medic::Sort do
2
2
 
3
3
  before do
4
4
  @subject = Object.new
@@ -0,0 +1,12 @@
1
+ describe Medic::SourceQueryBuilder do
2
+
3
+ before do
4
+ @subject = Medic::SourceQueryBuilder.new type: :dietary_protein do |query, sources, error|
5
+ end
6
+ end
7
+
8
+ it "has a query getter that returns an HKSourceQuery" do
9
+ @subject.query.should.be.kind_of? HKSourceQuery
10
+ end
11
+
12
+ end
@@ -0,0 +1,56 @@
1
+ describe Medic::StatisticsCollectionQueryBuilder do
2
+
3
+ before do
4
+ query_params = { type: :step_count, options: :sum, interval: :day }
5
+ @subject = Medic::StatisticsCollectionQueryBuilder.new query_params do |query, collection, error|
6
+ @block_contents = [query, collection, error]
7
+ end
8
+
9
+ query_params2 = { type: :step_count, options: :sum, interval: :day, update: true }
10
+ @subject_with_update = Medic::StatisticsCollectionQueryBuilder.new query_params2 do |query, collection, error|
11
+ @block_contents = [query, collection, error]
12
+ end
13
+ end
14
+
15
+ after do
16
+ @block_contents = nil
17
+ end
18
+
19
+ it "has a query getter that returns an HKStatisticsCollectionQuery" do
20
+ @subject.query.should.be.kind_of? HKStatisticsCollectionQuery
21
+ end
22
+
23
+ describe "initialize" do
24
+ it "sets initialResultsHandler when given block" do
25
+ @subject.query.initialResultsHandler.call(:query, :collection, :error)
26
+ @block_contents.should == [:query, :collection, :error]
27
+ end
28
+
29
+ context "when :update is given" do
30
+ it "sets statisticsUpdateHandler when given block" do
31
+ @subject_with_update.query.statisticsUpdateHandler.call(:query, :statistics, :collection, :error)
32
+ @block_contents.should == [:query, :collection, :error]
33
+ end
34
+ end
35
+
36
+ context "when :update isn't given" do
37
+ it "doesn't set statisticsUpdateHandler when given block" do
38
+ @subject.query.statisticsUpdateHandler.should == nil
39
+ @block_contents.should == nil
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "#initial_results_handler=" do
45
+ it "sets initialResultsHandler with callback" do
46
+ @subject.query.initialResultsHandler.should.respond_to? :call
47
+ end
48
+ end
49
+
50
+ describe "#statistics_update_handler=" do
51
+ it "sets statisticsUpdateHandler with callback" do
52
+ @subject_with_update.query.statisticsUpdateHandler.should.respond_to? :call
53
+ end
54
+ end
55
+
56
+ end
@@ -1,4 +1,4 @@
1
- describe "Medic::StatisticsOptions" do
1
+ describe Medic::StatisticsOptions do
2
2
 
3
3
  before do
4
4
  @subject = Object.new
@@ -0,0 +1,12 @@
1
+ describe Medic::StatisticsQueryBuilder do
2
+
3
+ before do
4
+ @subject = Medic::StatisticsQueryBuilder.new type: :step_count, options: :sum do |query, results, error|
5
+ end
6
+ end
7
+
8
+ it "has a query getter that returns an HKStatisticsQuery" do
9
+ @subject.query.should.be.kind_of? HKStatisticsQuery
10
+ end
11
+
12
+ end
@@ -1,12 +1,13 @@
1
- describe "Medic::Store" do
1
+ describe Medic::Store do
2
2
 
3
3
  before do
4
4
  @subject = Medic::Store.new
5
+ @hk_store = Medic::Store.hk_store
5
6
  end
6
7
 
7
8
  describe "#authorize" do
8
9
  it "calls #requestAuthorizationToShareTypes:readTypes:completion with correct args" do
9
- @subject.mock! 'requestAuthorizationToShareTypes:readTypes:completion' do |share, read, comp|
10
+ @hk_store.mock! 'requestAuthorizationToShareTypes:readTypes:completion' do |share, read, comp|
10
11
  share.should.be.kind_of? NSSet
11
12
  read.should.be.kind_of? NSSet
12
13
  comp.should.respond_to? :call
@@ -18,7 +19,7 @@ describe "Medic::Store" do
18
19
 
19
20
  describe "#authorized?" do
20
21
  it "calls #authorizationStatusForType with correct args" do
21
- @subject.mock! 'authorizationStatusForType' do |type|
22
+ @hk_store.mock! 'authorizationStatusForType' do |type|
22
23
  type.should.be.kind_of? HKObjectType
23
24
  false
24
25
  end
@@ -40,7 +41,7 @@ describe "Medic::Store" do
40
41
 
41
42
  describe "#biological_sex" do
42
43
  it "calls #biologicalSexWithError with correct args" do
43
- @subject.mock! 'biologicalSexWithError' do |error|
44
+ @hk_store.mock! 'biologicalSexWithError' do |error|
44
45
  error.should.be.kind_of? Pointer
45
46
  mock(:biologicalSex, return: HKBiologicalSexFemale)
46
47
  end
@@ -50,7 +51,7 @@ describe "Medic::Store" do
50
51
 
51
52
  describe "#blood_type" do
52
53
  it "calls #bloodTypeWithError with correct args" do
53
- @subject.mock! 'bloodTypeWithError' do |error|
54
+ @hk_store.mock! 'bloodTypeWithError' do |error|
54
55
  error.should.be.kind_of? Pointer
55
56
  mock(:bloodType, return: HKBloodTypeONegative)
56
57
  end
@@ -60,7 +61,7 @@ describe "Medic::Store" do
60
61
 
61
62
  describe "#date_of_birth" do
62
63
  it "calls #dateOfBirthWithError with correct args" do
63
- @subject.mock! 'dateOfBirthWithError' do |error|
64
+ @hk_store.mock! 'dateOfBirthWithError' do |error|
64
65
  error.should.be.kind_of? Pointer
65
66
  true
66
67
  end
@@ -70,18 +71,18 @@ describe "Medic::Store" do
70
71
 
71
72
  describe "#save" do
72
73
  it "calls #saveObject:withCompletion with correct args" do
73
- @subject.mock! 'saveObjects:withCompletion' do |object, comp|
74
- object.first.should.be.kind_of? HKObjectType
74
+ @hk_store.mock! 'saveObjects:withCompletion' do |object, comp|
75
+ object.first.should.be.kind_of? HKSample
75
76
  comp.should.respond_to? :call
76
77
  end
77
- steps = @subject.object_type(:step_count)
78
+ steps = { quantity_type: :step_count, quantity: 50 }
78
79
  @subject.save(steps){|success, error|}
79
80
  end
80
81
  end
81
82
 
82
83
  describe "#delete" do
83
84
  it "calls #deleteObject:withCompletion with correct args" do
84
- @subject.mock! 'deleteObject:withCompletion' do |object, comp|
85
+ @hk_store.mock! 'deleteObject:withCompletion' do |object, comp|
85
86
  object.should.be.kind_of? HKObjectType
86
87
  comp.should.respond_to? :call
87
88
  end
@@ -92,7 +93,7 @@ describe "Medic::Store" do
92
93
 
93
94
  describe "#execute" do
94
95
  it "calls #executeQuery with correct args" do
95
- @subject.mock! 'executeQuery' do |query|
96
+ @hk_store.mock! 'executeQuery' do |query|
96
97
  query.should.be.kind_of? HKQuery
97
98
  end
98
99
  query = HKSampleQuery.alloc.initWithSampleType(@subject.object_type(:step_count), predicate:nil, limit:HKObjectQueryNoLimit, sortDescriptors:nil, resultsHandler:->(q,r,e){})
@@ -106,7 +107,7 @@ describe "Medic::Store" do
106
107
 
107
108
  describe "#stop" do
108
109
  it "calls #stopQuery with correct args" do
109
- @subject.mock! 'stopQuery' do |query|
110
+ @hk_store.mock! 'stopQuery' do |query|
110
111
  query.should.be.kind_of? HKQuery
111
112
  end
112
113
  query = HKSampleQuery.alloc.initWithSampleType(@subject.object_type(:step_count), predicate:nil, limit:HKObjectQueryNoLimit, sortDescriptors:nil, resultsHandler:->(q,r,e){})
@@ -120,7 +121,7 @@ describe "Medic::Store" do
120
121
 
121
122
  describe "#enable_background_delivery" do
122
123
  it "calls #enableBackgroundDeliveryForType with correct args" do
123
- @subject.mock! 'enableBackgroundDeliveryForType:frequency:withCompletion' do |type, freq, comp|
124
+ @hk_store.mock! 'enableBackgroundDeliveryForType:frequency:withCompletion' do |type, freq, comp|
124
125
  type.should.be.kind_of? HKObjectType
125
126
  freq.should == HKUpdateFrequencyWeekly
126
127
  comp.should.respond_to? :call
@@ -135,7 +136,7 @@ describe "Medic::Store" do
135
136
 
136
137
  describe "#disable_background_delivery" do
137
138
  it "calls #disableBackgroundDeliveryForType:withCompletion with correct args" do
138
- @subject.mock! 'disableBackgroundDeliveryForType:withCompletion' do |type, comp|
139
+ @hk_store.mock! 'disableBackgroundDeliveryForType:withCompletion' do |type, comp|
139
140
  type.should.be.kind_of? HKObjectType
140
141
  comp.should.respond_to? :call
141
142
  end
@@ -149,7 +150,7 @@ describe "Medic::Store" do
149
150
 
150
151
  describe "#disable_all_background_delivery" do
151
152
  it "calls #disableAllBackgroundDeliveryWithCompletion with correct args" do
152
- @subject.mock! 'disableAllBackgroundDeliveryWithCompletion' do |comp|
153
+ @hk_store.mock! 'disableAllBackgroundDeliveryWithCompletion' do |comp|
153
154
  comp.should.respond_to? :call
154
155
  end
155
156
  @subject.disable_all_background_delivery{|success, error|}
@@ -1,4 +1,4 @@
1
- describe "Medic::Types" do
1
+ describe Medic::Types do
2
2
 
3
3
  before do
4
4
  @subject = Object.new
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: medic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ryan Linton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-12-20 00:00:00.000000000 Z
11
+ date: 2015-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -48,39 +48,40 @@ files:
48
48
  - README.md
49
49
  - lib/medic.rb
50
50
  - lib/medic/anchor.rb
51
- - lib/medic/anchored_object_query.rb
52
- - lib/medic/correlation_query.rb
51
+ - lib/medic/anchored_object_query_builder.rb
52
+ - lib/medic/correlation_query_builder.rb
53
53
  - lib/medic/finders.rb
54
54
  - lib/medic/hk_constants.rb
55
55
  - lib/medic/interval.rb
56
56
  - lib/medic/medic.rb
57
- - lib/medic/observer_query.rb
57
+ - lib/medic/observer_query_builder.rb
58
58
  - lib/medic/predicate.rb
59
59
  - lib/medic/query_options.rb
60
- - lib/medic/sample_query.rb
60
+ - lib/medic/sample_query_builder.rb
61
61
  - lib/medic/sort.rb
62
- - lib/medic/source_query.rb
63
- - lib/medic/statistics_collection_query.rb
62
+ - lib/medic/source_query_builder.rb
63
+ - lib/medic/statistics_collection_query_builder.rb
64
64
  - lib/medic/statistics_options.rb
65
- - lib/medic/statistics_query.rb
65
+ - lib/medic/statistics_query_builder.rb
66
66
  - lib/medic/store.rb
67
67
  - lib/medic/types.rb
68
+ - lib/medic/units.rb
68
69
  - lib/medic/version.rb
69
70
  - spec/medic/anchor.rb
70
- - spec/medic/anchored_object_query_spec.rb
71
- - spec/medic/correlation_query_spec.rb
71
+ - spec/medic/anchored_object_query_builder_spec.rb
72
+ - spec/medic/correlation_query_builder_spec.rb
72
73
  - spec/medic/hk_constants_spec.rb
73
74
  - spec/medic/interval_spec.rb
74
75
  - spec/medic/medic_spec.rb
75
- - spec/medic/observer_query_spec.rb
76
+ - spec/medic/observer_query_builder_spec.rb
76
77
  - spec/medic/predicate_spec.rb
77
78
  - spec/medic/query_options_spec.rb
78
- - spec/medic/sample_query_spec.rb
79
+ - spec/medic/sample_query_builder_spec.rb
79
80
  - spec/medic/sort_spec.rb
80
- - spec/medic/source_query_spec.rb
81
- - spec/medic/statistics_collection_query_spec.rb
81
+ - spec/medic/source_query_builder_spec.rb
82
+ - spec/medic/statistics_collection_query_builder_spec.rb
82
83
  - spec/medic/statistics_options_spec.rb
83
- - spec/medic/statistics_query_spec.rb
84
+ - spec/medic/statistics_query_builder_spec.rb
84
85
  - spec/medic/store_spec.rb
85
86
  - spec/medic/types_spec.rb
86
87
  homepage: https://github.com/ryanlntn/medic
@@ -103,25 +104,25 @@ required_rubygems_version: !ruby/object:Gem::Requirement
103
104
  version: '0'
104
105
  requirements: []
105
106
  rubyforge_project:
106
- rubygems_version: 2.4.2
107
+ rubygems_version: 2.4.6
107
108
  signing_key:
108
109
  specification_version: 4
109
110
  summary: A RubyMotion Wrapper for HealthKit
110
111
  test_files:
111
112
  - spec/medic/anchor.rb
112
- - spec/medic/anchored_object_query_spec.rb
113
- - spec/medic/correlation_query_spec.rb
113
+ - spec/medic/anchored_object_query_builder_spec.rb
114
+ - spec/medic/correlation_query_builder_spec.rb
114
115
  - spec/medic/hk_constants_spec.rb
115
116
  - spec/medic/interval_spec.rb
116
117
  - spec/medic/medic_spec.rb
117
- - spec/medic/observer_query_spec.rb
118
+ - spec/medic/observer_query_builder_spec.rb
118
119
  - spec/medic/predicate_spec.rb
119
120
  - spec/medic/query_options_spec.rb
120
- - spec/medic/sample_query_spec.rb
121
+ - spec/medic/sample_query_builder_spec.rb
121
122
  - spec/medic/sort_spec.rb
122
- - spec/medic/source_query_spec.rb
123
- - spec/medic/statistics_collection_query_spec.rb
123
+ - spec/medic/source_query_builder_spec.rb
124
+ - spec/medic/statistics_collection_query_builder_spec.rb
124
125
  - spec/medic/statistics_options_spec.rb
125
- - spec/medic/statistics_query_spec.rb
126
+ - spec/medic/statistics_query_builder_spec.rb
126
127
  - spec/medic/store_spec.rb
127
128
  - spec/medic/types_spec.rb
@@ -1,39 +0,0 @@
1
- module Medic
2
- class StatisticsCollectionQuery < HKStatisticsCollectionQuery
3
-
4
- include Medic::Types
5
- include Medic::Predicate
6
- include Medic::StatisticsOptions
7
- include Medic::Anchor
8
- include Medic::Interval
9
-
10
- def initialize(args={})
11
- self.initWithQuantityType(object_type(args[:type]),
12
- quantitySamplePredicate: predicate(args),
13
- options: options_for_stat_query(args[:options]),
14
- anchorDate: anchor_for_symbol(args[:anchor_date] || args[:anchor] || args[:date] || NSDate.date),
15
- intervalComponents: interval(args[:interval_components] || args[:interval])
16
- )
17
- self.initialResultsHandler = Proc.new if block_given?
18
- self
19
- end
20
-
21
- alias_method :initial_results_handler, :initialResultsHandler
22
-
23
- def initial_results_handler=(callback=Proc.new)
24
- self.initialResultsHandler = callback
25
- end
26
-
27
- alias_method :statistics_update_handler, :statisticsUpdateHandler
28
-
29
- def statistics_update_handler=(callback=Proc.new)
30
- self.statisticsUpdateHandler = callback
31
- end
32
-
33
- alias_method :anchor, :anchorDate
34
- alias_method :anchor_date, :anchorDate
35
- alias_method :interval, :intervalComponents
36
- alias_method :interval_components, :intervalComponents
37
-
38
- end
39
- end
@@ -1,12 +0,0 @@
1
- describe "Medic::AnchoredObjectQuery" do
2
-
3
- before do
4
- @subject = Medic::AnchoredObjectQuery.new type: :step_count do |query, results, new_anchor, error|
5
- end
6
- end
7
-
8
- it "is a subclass of HKAnchoredObjectQuery" do
9
- @subject.should.be.kind_of? HKAnchoredObjectQuery
10
- end
11
-
12
- end
@@ -1,12 +0,0 @@
1
- describe "Medic::ObserverQuery" do
2
-
3
- before do
4
- @subject = Medic::ObserverQuery.new type: :step_count do |query, completion, error|
5
- end
6
- end
7
-
8
- it "is a subclass of HKObserverQuery" do
9
- @subject.should.be.kind_of? HKObserverQuery
10
- end
11
-
12
- end
@@ -1,12 +0,0 @@
1
- describe "Medic::SampleQuery" do
2
-
3
- before do
4
- @subject = Medic::SampleQuery.new type: :dietary_protein, limit: 7 do |query, results, error|
5
- end
6
- end
7
-
8
- it "is a subclass of HKSampleQuery" do
9
- @subject.should.be.kind_of? HKSampleQuery
10
- end
11
-
12
- end
@@ -1,12 +0,0 @@
1
- describe "Medic::SourceQuery" do
2
-
3
- before do
4
- @subject = Medic::SourceQuery.new type: :dietary_protein do |query, sources, error|
5
- end
6
- end
7
-
8
- it "is a subclass of HKSourceQuery" do
9
- @subject.should.be.kind_of? HKSourceQuery
10
- end
11
-
12
- end
@@ -1,27 +0,0 @@
1
- describe "Medic::StatisticsCollectionQuery" do
2
-
3
- before do
4
- @interval = NSDateComponents.new
5
- @interval.day = 1
6
- @subject = Medic::StatisticsCollectionQuery.new(type: :step_count, options: :sum, interval: @interval)
7
- end
8
-
9
- it "is a subclass of HKStatisticsCollectionQuery" do
10
- @subject.should.be.kind_of? HKStatisticsCollectionQuery
11
- end
12
-
13
- describe "#initial_results_handler=" do
14
- it "sets initialResultsHandler with callback" do
15
- @subject.initial_results_handler = ->(){}
16
- @subject.initialResultsHandler.should.respond_to? :call
17
- end
18
- end
19
-
20
- describe "#statistics_update_handler=" do
21
- it "sets statisticsUpdateHandler with callback" do
22
- @subject.statistics_update_handler = ->(){}
23
- @subject.statisticsUpdateHandler.should.respond_to? :call
24
- end
25
- end
26
-
27
- end
@@ -1,12 +0,0 @@
1
- describe "Medic::StatisticsQuery" do
2
-
3
- before do
4
- @subject = Medic::StatisticsQuery.new type: :step_count, options: :sum do |query, results, error|
5
- end
6
- end
7
-
8
- it "is a subclass of HKStatisticsQuery" do
9
- @subject.should.be.kind_of? HKStatisticsQuery
10
- end
11
-
12
- end