tanita-api-client 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +15 -0
- data/README.md +13 -9
- data/lib/tanita/api/client/base.rb +1 -119
- data/lib/tanita/api/client/base_api_client.rb +112 -0
- data/lib/tanita/api/client/base_entity.rb +27 -0
- data/lib/tanita/api/client/class_builder.rb +61 -0
- data/lib/tanita/api/client/helpers.rb +5 -1
- data/lib/tanita/api/client/version.rb +1 -1
- data/lib/tanita/api/client.rb +15 -12
- data/tanita-api-client.gemspec +1 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 91859c1415a0fc78e01c01c1e615acdca193ce8ec887abaa19ce5d3e1353285f
|
4
|
+
data.tar.gz: 4b875b46afb595f6ccb84fb6776da2f4527ab9b099274131251b0a65c2ceaba9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bcd9de5af29bcf2c760a501dab1f4165c6a9102960d64ca23c10d3fbbbeadccc96ccdafd92da4bf776b2778f4d65a1f5dd9976c952317b835a8bc8ec934986ad
|
7
|
+
data.tar.gz: 1193a310b0014f32f16cf6b5819960b6326a8ef486582007d0a4a179c9ce8fc0788dea6d0a2c67dbefd61c600a9ed731621d4044e22b955aaef54512c00240f2
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -92,7 +92,7 @@ result = api.status
|
|
92
92
|
result = api.status(from: Date.current.ago(1.month), to: Date.current)
|
93
93
|
|
94
94
|
# list the body-weight data
|
95
|
-
result.items.each{|item| puts "#{Time.at(item
|
95
|
+
result.items.each{|item| puts "#{Time.at(item.measured_at).strftime('%F %R')} => #{item.weight}" }
|
96
96
|
2019-10-10 08:09 => 66.7
|
97
97
|
2019-10-11 09:02 => 66.5
|
98
98
|
2019-10-13 08:22 => 66.7
|
@@ -101,23 +101,27 @@ result.items.each{|item| puts "#{Time.at(item[:measured_at]).strftime('%F %R')}
|
|
101
101
|
|
102
102
|
# Result of Innerscan Api
|
103
103
|
result = Tanita::Api::Client::Innerscan.new.status
|
104
|
-
|
105
|
-
|
104
|
+
=> #<Tanita::Api::Client::Result:70199592389780 properties=birth_date,height,sex,items>
|
105
|
+
result.items[0]
|
106
|
+
=> #<Tanita::Api::Client::InnerscanItem:70199597695880 properties=measured_at,registered_at,model,weight,body_fat,muscle_mass,physique_rating,visceral_fat_rating,basal_metabolic_rate,metabolic_age,bone_mass>
|
107
|
+
result.items[0].weight
|
108
|
+
=> 66.7
|
106
109
|
|
107
110
|
# Result of Sphygmomanometer Api
|
108
111
|
result = Tanita::Api::Client::Sphygmomanometer.new.status
|
109
|
-
result.items[0]
|
110
|
-
=>
|
112
|
+
result.items[0]
|
113
|
+
=> #<Tanita::Api::Client::SphygmomanometerItem:70199592475760 properties=measured_at,registered_at,model,maximal_pressure,minimal_pressure,pulse>
|
111
114
|
|
112
115
|
# Result of Pedometer Api
|
113
116
|
result = Tanita::Api::Client::Pedometer.new.status
|
114
|
-
result.items[0]
|
115
|
-
=>
|
117
|
+
result.items[0]
|
118
|
+
=> #<Tanita::Api::Client::PedometerItem:70199605021160 properties=measured_at,registered_at,model,steps,exercise,calories>
|
119
|
+
|
116
120
|
|
117
121
|
# Result of Smug Api
|
118
122
|
result = Tanita::Api::Client::Smug.new.status
|
119
|
-
result.items[0]
|
120
|
-
=>
|
123
|
+
result.items[0]
|
124
|
+
=> #<Tanita::Api::Client::SmugItem:70199600803680 properties=measured_at,registered_at,model,urinary_sugar>
|
121
125
|
|
122
126
|
# common attributes of Result class
|
123
127
|
result.birth_date # [Date]
|
@@ -1,11 +1,9 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require 'time'
|
4
|
-
require 'tanita/api/client/helpers'
|
5
|
-
|
6
3
|
module Tanita
|
7
4
|
module Api
|
8
5
|
module Client
|
6
|
+
|
9
7
|
module Scope
|
10
8
|
INNERSCAN = 'innerscan'
|
11
9
|
SPHYGMOMANOMETER = 'sphygmomanometer'
|
@@ -19,122 +17,6 @@ module Tanita
|
|
19
17
|
class Error < StandardError
|
20
18
|
end
|
21
19
|
|
22
|
-
DATE_TYPE_REGISTERD_AT = 0
|
23
|
-
DATE_TYPE_MEASURED_AT = 1
|
24
|
-
|
25
|
-
class BaseApiClient
|
26
|
-
include HttpHelper
|
27
|
-
|
28
|
-
def initialize(access_token: nil, date_type: DATE_TYPE_MEASURED_AT)
|
29
|
-
config = Tanita::Api::Client.configuration
|
30
|
-
@access_token = access_token || config.access_token
|
31
|
-
raise Error.new("param:'access_token' is required.'") if @access_token.nil?
|
32
|
-
|
33
|
-
@date_type = date_type
|
34
|
-
raise Error.new("param:'date_type' is invalid.'") unless [DATE_TYPE_REGISTERD_AT, DATE_TYPE_MEASURED_AT].include? date_type
|
35
|
-
end
|
36
|
-
|
37
|
-
def status(
|
38
|
-
from: nil,
|
39
|
-
to: nil
|
40
|
-
)
|
41
|
-
tags = measurement_tags.values.map { |i| i[:code] }.join(',')
|
42
|
-
params = {
|
43
|
-
:access_token => @access_token,
|
44
|
-
:date => @date_type,
|
45
|
-
:tag => tags
|
46
|
-
}
|
47
|
-
params[:from] = time_format(from) unless from.nil?
|
48
|
-
params[:to] = time_format(to) unless to.nil?
|
49
|
-
res = request(endpoint, params)
|
50
|
-
Result.new(:client => self, :response => res)
|
51
|
-
end
|
52
|
-
|
53
|
-
def endpoint
|
54
|
-
raise NotImplementedError
|
55
|
-
end
|
56
|
-
|
57
|
-
def measurement_tags
|
58
|
-
raise NotImplementedError
|
59
|
-
end
|
60
|
-
|
61
|
-
def find_measurement_tag(code:)
|
62
|
-
return @inverted_measurement[code] unless @inverted_measurement.nil?
|
63
|
-
|
64
|
-
@inverted_measurement = {}
|
65
|
-
measurement_tags.each do |m_name, m_info|
|
66
|
-
@inverted_measurement[m_info[:code]] = {:name => m_name, :type => m_info[:type]}
|
67
|
-
end
|
68
|
-
@inverted_measurement[code]
|
69
|
-
end
|
70
|
-
|
71
|
-
def date_key
|
72
|
-
case @date_type
|
73
|
-
when DATE_TYPE_REGISTERD_AT
|
74
|
-
:registered_at
|
75
|
-
when DATE_TYPE_MEASURED_AT
|
76
|
-
:measured_at
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
private
|
81
|
-
|
82
|
-
def time_format(time)
|
83
|
-
time.strftime('%Y%m%d%H%M%S')
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
class Result
|
88
|
-
include HttpHelper
|
89
|
-
|
90
|
-
# [Date]
|
91
|
-
attr_reader :birth_date
|
92
|
-
|
93
|
-
# [Float] (centimeter)
|
94
|
-
attr_reader :height
|
95
|
-
|
96
|
-
# [String] 'male' or 'female'
|
97
|
-
attr_reader :sex
|
98
|
-
|
99
|
-
# [Array<Hash>]
|
100
|
-
attr_reader :items
|
101
|
-
|
102
|
-
def initialize(client:, response:)
|
103
|
-
@client = client
|
104
|
-
result = parse_json(response.body)
|
105
|
-
@birth_date = Date.parse(result[:birth_date])
|
106
|
-
@height = result[:height].to_f
|
107
|
-
@sex = result[:sex]
|
108
|
-
@items = build_items(result[:data])
|
109
|
-
end
|
110
|
-
|
111
|
-
private
|
112
|
-
|
113
|
-
def build_items(raw_items)
|
114
|
-
item_dic = {}
|
115
|
-
raw_items.each do |item|
|
116
|
-
date = item[:date]
|
117
|
-
model = item[:model]
|
118
|
-
key = "#{date}_#{model}"
|
119
|
-
measurement = @client.find_measurement_tag(:code => item[:tag])
|
120
|
-
value = cast(:value => item[:keydata], :type => measurement[:type])
|
121
|
-
item_dic[key] ||= {}
|
122
|
-
item_dic[key][@client.date_key] = Time.parse("#{date} +09:00").to_i unless item_dic[key].key? :date
|
123
|
-
item_dic[key][:model] = model unless item_dic[key].key? :model
|
124
|
-
item_dic[key][measurement[:name]] = value
|
125
|
-
end
|
126
|
-
# sort by date in ascending order
|
127
|
-
item_dic.values.sort_by { |dic| dic[@client.date_key] }
|
128
|
-
end
|
129
|
-
|
130
|
-
def cast(value:, type:)
|
131
|
-
return value if value.nil?
|
132
|
-
return value.to_i if type == Integer
|
133
|
-
return value.to_f if type == Float
|
134
|
-
|
135
|
-
value
|
136
|
-
end
|
137
|
-
end
|
138
20
|
end
|
139
21
|
end
|
140
22
|
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'time'
|
4
|
+
require 'tanita/api/client/helpers'
|
5
|
+
|
6
|
+
module Tanita
|
7
|
+
module Api
|
8
|
+
module Client
|
9
|
+
DATE_TYPE_REGISTERD_AT = 0
|
10
|
+
DATE_TYPE_MEASURED_AT = 1
|
11
|
+
|
12
|
+
class BaseApiClient
|
13
|
+
include HttpHelper
|
14
|
+
|
15
|
+
def self.endpoint
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.properties
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize(access_token: nil, date_type: DATE_TYPE_MEASURED_AT)
|
24
|
+
config = Tanita::Api::Client.configuration
|
25
|
+
@access_token = access_token || config.access_token
|
26
|
+
raise Error.new("param:'access_token' is required.'") if @access_token.nil?
|
27
|
+
|
28
|
+
@date_type = date_type
|
29
|
+
raise Error.new("param:'date_type' is invalid.'") unless [DATE_TYPE_REGISTERD_AT, DATE_TYPE_MEASURED_AT].include? date_type
|
30
|
+
|
31
|
+
ClassBuilder.load
|
32
|
+
end
|
33
|
+
|
34
|
+
def status(
|
35
|
+
from: nil,
|
36
|
+
to: nil
|
37
|
+
)
|
38
|
+
tags = self.class.properties.values.map { |i| i[:code] }.join(',')
|
39
|
+
params = {
|
40
|
+
:access_token => @access_token,
|
41
|
+
:date => @date_type,
|
42
|
+
:tag => tags
|
43
|
+
}
|
44
|
+
params[:from] = time_format(from) unless from.nil?
|
45
|
+
params[:to] = time_format(to) unless to.nil?
|
46
|
+
res = request(self.class.endpoint, params)
|
47
|
+
build_result(res)
|
48
|
+
end
|
49
|
+
|
50
|
+
def inspect
|
51
|
+
"\#<#{self.class}:#{object_id}>"
|
52
|
+
end
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
def build_result(res)
|
57
|
+
result = parse_json(res.body)
|
58
|
+
Result.new(
|
59
|
+
:birth_date => Date.parse(result[:birth_date]),
|
60
|
+
:height => result[:height].to_f,
|
61
|
+
:sex => result[:sex],
|
62
|
+
:items => build_result_items(:raw_items => result[:data])
|
63
|
+
)
|
64
|
+
end
|
65
|
+
|
66
|
+
def build_result_items(raw_items:)
|
67
|
+
item_dic = {}
|
68
|
+
raw_items.each do |item|
|
69
|
+
date = item[:date]
|
70
|
+
model = item[:model]
|
71
|
+
key = "#{date}_#{model}"
|
72
|
+
property = find_property_by_code(:code => item[:tag])
|
73
|
+
value = cast(:value => item[:keydata], :type => property[:type])
|
74
|
+
item_dic[key] ||= {}
|
75
|
+
item_dic[key][date_key] = Time.parse("#{date} +09:00").to_i unless item_dic[key].key? :date
|
76
|
+
item_dic[key][:model] = model unless item_dic[key].key? :model
|
77
|
+
item_dic[key][property[:name]] = value
|
78
|
+
end
|
79
|
+
items = item_dic.values.sort_by { |dic| dic[date_key] } # sort by date in ascending order
|
80
|
+
items.map { |_item_dic| eval "#{self.class}Item.new _item_dic" }
|
81
|
+
end
|
82
|
+
|
83
|
+
def cast(value:, type:)
|
84
|
+
return value if value.nil?
|
85
|
+
return value.to_i if type == Integer
|
86
|
+
return value.to_f if type == Float
|
87
|
+
|
88
|
+
value
|
89
|
+
end
|
90
|
+
|
91
|
+
def find_property_by_code(code:)
|
92
|
+
return @property_code_dic[code] unless @property_code_dic.nil?
|
93
|
+
|
94
|
+
@property_code_dic = {}
|
95
|
+
self.class.properties.each do |m_name, m_info|
|
96
|
+
@property_code_dic[m_info[:code]] = {:name => m_name, :type => m_info[:type]}
|
97
|
+
end
|
98
|
+
@property_code_dic[code]
|
99
|
+
end
|
100
|
+
|
101
|
+
def date_key
|
102
|
+
case @date_type
|
103
|
+
when DATE_TYPE_REGISTERD_AT
|
104
|
+
:registered_at
|
105
|
+
when DATE_TYPE_MEASURED_AT
|
106
|
+
:measured_at
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tanita
|
4
|
+
module Api
|
5
|
+
module Client
|
6
|
+
class BaseEntity
|
7
|
+
def initialize(property_values = {})
|
8
|
+
@properties = []
|
9
|
+
@cached_property_values = {}
|
10
|
+
@cached_property_values.merge!(property_values)
|
11
|
+
end
|
12
|
+
|
13
|
+
def to_h
|
14
|
+
ret = {}
|
15
|
+
self.class.properties.each do |property|
|
16
|
+
ret[property.to_sym] = eval property.to_s
|
17
|
+
end
|
18
|
+
ret
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
"\#<#{self.class}:#{object_id} properties=#{self.class.properties.join(',')}>"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Tanita
|
4
|
+
module Api
|
5
|
+
module Client
|
6
|
+
class ClassBuilder
|
7
|
+
def self.load
|
8
|
+
return if loaded
|
9
|
+
|
10
|
+
create_class('Result', %i[birth_date height sex items])
|
11
|
+
base_properties = %i[measured_at registered_at model]
|
12
|
+
[Innerscan, Sphygmomanometer, Pedometer, Smug].each do |klass|
|
13
|
+
klass_name = klass.to_s.split('::')[-1] + 'Item'
|
14
|
+
properties = base_properties + klass.properties.keys
|
15
|
+
create_class(klass_name, properties)
|
16
|
+
end
|
17
|
+
@loaded = true
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.loaded
|
21
|
+
@loaded || false
|
22
|
+
end
|
23
|
+
private_class_method :loaded
|
24
|
+
|
25
|
+
def self.create_class(class_name, property_names = [])
|
26
|
+
super_klass = Class.new(BaseEntity)
|
27
|
+
klass = Tanita::Api::Client.const_set(class_name, super_klass)
|
28
|
+
define_properties_reader(klass)
|
29
|
+
property_names.each do |property_name|
|
30
|
+
klass.properties << property_name if klass.respond_to?(:properties)
|
31
|
+
define_getter_and_setter(klass, property_name)
|
32
|
+
end
|
33
|
+
klass.properties.freeze if klass.respond_to?(:properties)
|
34
|
+
end
|
35
|
+
private_class_method :create_class
|
36
|
+
|
37
|
+
def self.define_properties_reader(klass)
|
38
|
+
klass.class_eval do
|
39
|
+
def self.properties
|
40
|
+
@properties = [] if @properties.nil?
|
41
|
+
@properties
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
private_class_method :define_properties_reader
|
46
|
+
|
47
|
+
def self.define_getter_and_setter(klass, property_name)
|
48
|
+
klass.class_eval do
|
49
|
+
define_method(property_name.to_sym) do
|
50
|
+
@cached_property_values[property_name.to_sym]
|
51
|
+
end
|
52
|
+
define_method("#{property_name}=".to_sym) do |value|
|
53
|
+
@cached_property_values[property_name.to_sym] = value
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
private_class_method :define_getter_and_setter
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -11,7 +11,7 @@ module Tanita
|
|
11
11
|
AUTH_URL_PATH = '/oauth/auth'
|
12
12
|
AUTH_URL = "#{BASE_URL}#{AUTH_URL_PATH}"
|
13
13
|
|
14
|
-
TOKEN_URL_PATH =
|
14
|
+
TOKEN_URL_PATH = '/oauth/token'
|
15
15
|
TOKEN_URL = "#{BASE_URL}#{TOKEN_URL_PATH}"
|
16
16
|
|
17
17
|
DEFAULT_REDIRECT_URI = "#{BASE_URL}/success.html"
|
@@ -37,6 +37,10 @@ module Tanita
|
|
37
37
|
rescue JSON::ParserError => e
|
38
38
|
raise Error.new("JSON::ParseError: '#{e}'\nstr:#{str}")
|
39
39
|
end
|
40
|
+
|
41
|
+
def time_format(time)
|
42
|
+
time.strftime('%Y%m%d%H%M%S')
|
43
|
+
end
|
40
44
|
end
|
41
45
|
end
|
42
46
|
end
|
data/lib/tanita/api/client.rb
CHANGED
@@ -1,9 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
3
|
+
Dir[
|
4
|
+
File.join(
|
5
|
+
File.dirname(__FILE__),
|
6
|
+
'client',
|
7
|
+
'*'
|
8
|
+
)
|
9
|
+
].sort.each { |f| require f }
|
7
10
|
|
8
11
|
module Tanita
|
9
12
|
module Api
|
@@ -67,11 +70,11 @@ module Tanita
|
|
67
70
|
end
|
68
71
|
|
69
72
|
class Innerscan < BaseApiClient
|
70
|
-
def endpoint
|
73
|
+
def self.endpoint
|
71
74
|
'/status/innerscan.json'
|
72
75
|
end
|
73
76
|
|
74
|
-
def
|
77
|
+
def self.properties
|
75
78
|
{
|
76
79
|
:weight => {:code => '6021', :type => Float},
|
77
80
|
:body_fat => {:code => '6022', :type => Float},
|
@@ -86,11 +89,11 @@ module Tanita
|
|
86
89
|
end
|
87
90
|
|
88
91
|
class Sphygmomanometer < BaseApiClient
|
89
|
-
def endpoint
|
92
|
+
def self.endpoint
|
90
93
|
'/status/sphygmomanometer.json'
|
91
94
|
end
|
92
95
|
|
93
|
-
def
|
96
|
+
def self.properties
|
94
97
|
{
|
95
98
|
:maximal_pressure => {:code => '622E', :type => Integer},
|
96
99
|
:minimal_pressure => {:code => '622F', :type => Integer},
|
@@ -100,11 +103,11 @@ module Tanita
|
|
100
103
|
end
|
101
104
|
|
102
105
|
class Pedometer < BaseApiClient
|
103
|
-
def endpoint
|
106
|
+
def self.endpoint
|
104
107
|
'/status/pedometer.json'
|
105
108
|
end
|
106
109
|
|
107
|
-
def
|
110
|
+
def self.properties
|
108
111
|
{
|
109
112
|
:steps => {:code => '6331', :type => Integer},
|
110
113
|
:exercise => {:code => '6335', :type => Integer},
|
@@ -114,11 +117,11 @@ module Tanita
|
|
114
117
|
end
|
115
118
|
|
116
119
|
class Smug < BaseApiClient
|
117
|
-
def endpoint
|
120
|
+
def self.endpoint
|
118
121
|
'/status/smug.json'
|
119
122
|
end
|
120
123
|
|
121
|
-
def
|
124
|
+
def self.properties
|
122
125
|
{
|
123
126
|
:urinary_sugar => {:code => '6240', :type => Integer}
|
124
127
|
}
|
data/tanita-api-client.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.metadata['homepage_uri'] = spec.homepage
|
20
20
|
spec.metadata['source_code_uri'] = 'https://github.com/koshilife/tanita-api-ruby-client'
|
21
21
|
spec.metadata['changelog_uri'] = "#{spec.metadata['source_code_uri']}/blob/master/CHANGELOG.md"
|
22
|
+
spec.metadata['documentation_uri'] = 'https://www.rubydoc.info/gems/tanita-api-client/'
|
22
23
|
|
23
24
|
# Specify which files should be added to the gem when it is released.
|
24
25
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tanita-api-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kenji Koshikawa
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -87,6 +87,9 @@ files:
|
|
87
87
|
- bin/setup
|
88
88
|
- lib/tanita/api/client.rb
|
89
89
|
- lib/tanita/api/client/base.rb
|
90
|
+
- lib/tanita/api/client/base_api_client.rb
|
91
|
+
- lib/tanita/api/client/base_entity.rb
|
92
|
+
- lib/tanita/api/client/class_builder.rb
|
90
93
|
- lib/tanita/api/client/configuration.rb
|
91
94
|
- lib/tanita/api/client/helpers.rb
|
92
95
|
- lib/tanita/api/client/version.rb
|
@@ -98,6 +101,7 @@ metadata:
|
|
98
101
|
homepage_uri: https://github.com/koshilife/tanita-api-ruby-client
|
99
102
|
source_code_uri: https://github.com/koshilife/tanita-api-ruby-client
|
100
103
|
changelog_uri: https://github.com/koshilife/tanita-api-ruby-client/blob/master/CHANGELOG.md
|
104
|
+
documentation_uri: https://www.rubydoc.info/gems/tanita-api-client/
|
101
105
|
post_install_message:
|
102
106
|
rdoc_options: []
|
103
107
|
require_paths:
|