yt 0.18.0 → 0.19.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 +4 -4
- data/.gitignore +1 -0
- data/CHANGELOG.md +23 -0
- data/README.md +2 -4
- data/lib/yt/collections/partnered_channels.rb +0 -20
- data/lib/yt/models/base.rb +0 -2
- data/lib/yt/models/channel.rb +0 -7
- data/lib/yt/models/policy.rb +0 -5
- data/lib/yt/models/video.rb +0 -10
- data/lib/yt/version.rb +1 -1
- data/spec/requests/as_account/channel_spec.rb +0 -5
- data/spec/requests/as_account/video_spec.rb +0 -5
- data/spec/requests/as_content_owner/channel_spec.rb +0 -16
- data/spec/requests/as_content_owner/content_owner_spec.rb +0 -8
- data/spec/requests/as_content_owner/video_spec.rb +0 -16
- metadata +1 -5
- data/lib/yt/associations/has_viewer_percentages.rb +0 -40
- data/lib/yt/collections/viewer_percentages.rb +0 -56
- data/spec/requests/as_content_owner/viewer_percentages_spec.rb +0 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 17691684dae81110d7d3ff39e8952823deedc5ac
|
4
|
+
data.tar.gz: a2438b53994ef551b3525a310db27990695a7f1d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9994436e29b6ef5b5bc3533db28e5f40e2839948076f30cac3794769b4e962cd0dee3dc88e4f1f52641420cd401b62070d8cc8bcf9aae4eabf349b397bfa6408
|
7
|
+
data.tar.gz: 98f99214f24da915e60247d4192579b93b5579e5e16e83cde009bd017f21c46c5a9a6c22a7451b291c1e4afd69fc130570b29fd419b37b1d96d9148a0469e6fb
|
data/.gitignore
CHANGED
data/CHANGELOG.md
CHANGED
@@ -6,6 +6,29 @@ For more information about changelogs, check
|
|
6
6
|
[Keep a Changelog](http://keepachangelog.com) and
|
7
7
|
[Vandamme](http://tech-angels.github.io/vandamme).
|
8
8
|
|
9
|
+
## 0.19.0 - 2015-04-28
|
10
|
+
|
11
|
+
**How to upgrade**
|
12
|
+
|
13
|
+
If your code never calls `partnered_channels.includes(:viewer_percentages)` on
|
14
|
+
a Yt::ContentOwner, then you are good to go.
|
15
|
+
|
16
|
+
If it does, then be aware that viewer percentage is not eager-loaded anymore,
|
17
|
+
so the call above is equivalent to `partenered_channels`. The reason is that
|
18
|
+
viewer percentage *requires* a time-range, and using a default range of the
|
19
|
+
last 3 months can generate more confusion than added value.
|
20
|
+
|
21
|
+
Also if your code still uses the deprecated:
|
22
|
+
|
23
|
+
- `.viewer_percentages` method, replace with `.viewer_percentage`.
|
24
|
+
- `policy.time_updated` method, replace with `policy.updated_at`.
|
25
|
+
- `video.uploaded?` method, replace with `video.uploading?`.
|
26
|
+
|
27
|
+
* [REMOVAL] Remove `.includes(:viewer_percentages)` on `content_owner.partnered_channels`.
|
28
|
+
* [REMOVAL] Remove deprecated `viewer_percentages` (use `viewer_percentage` instead)
|
29
|
+
* [REMOVAL] Remove deprecated `policy.time_updated` (use `updated_at` instead)
|
30
|
+
* [REMOVAL] Remove deprecated `video.uploaded?` (use `uploading?` instead)
|
31
|
+
|
9
32
|
## 0.18.0 - 2015-04-28
|
10
33
|
|
11
34
|
**How to upgrade**
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@ Yt - a Ruby client for the YouTube API
|
|
3
3
|
|
4
4
|
Yt helps you write apps that need to interact with YouTube.
|
5
5
|
|
6
|
-
The **
|
6
|
+
The **source code** is available on [GitHub](https://github.com/Fullscreen/yt) and the **documentation** on [RubyDoc](http://www.rubydoc.info/gems/yt/frames).
|
7
7
|
|
8
8
|
[](https://travis-ci.org/Fullscreen/yt)
|
9
9
|
[](https://coveralls.io/r/Fullscreen/yt)
|
@@ -41,7 +41,7 @@ To install on your system, run
|
|
41
41
|
|
42
42
|
To use inside a bundled Ruby project, add this line to the Gemfile:
|
43
43
|
|
44
|
-
gem 'yt', '~> 0.
|
44
|
+
gem 'yt', '~> 0.19.0'
|
45
45
|
|
46
46
|
Since the gem follows [Semantic Versioning](http://semver.org),
|
47
47
|
indicating the full version in your Gemfile (~> *major*.*minor*.*patch*)
|
@@ -115,8 +115,6 @@ content_owner = Yt::ContentOwner.new owner_name: 'CMSname', access_token: 'ya29.
|
|
115
115
|
content_owner.partnered_channels.count #=> 12
|
116
116
|
content_owner.partnered_channels.map &:title #=> ["Fullscreen", "Best of Fullscreen", ...]
|
117
117
|
content_owner.partnered_channels.where(part: 'statistics').map &:subscriber_count #=> [136925, 56945, ...]
|
118
|
-
content_owner.partnered_channels.includes(:viewer_percentages).map &:viewer_percentages #=> [{female: {'18-24' => 12.12,…}…}, {female: {'18-24' => 40.12,…}…}, …]
|
119
|
-
|
120
118
|
|
121
119
|
content_owner.claims.where(q: 'Fullscreen').count #=> 24
|
122
120
|
content_owner.claims.first #=> #<Yt::Models::Claim @id=...>
|
@@ -6,26 +6,6 @@ module Yt
|
|
6
6
|
|
7
7
|
private
|
8
8
|
|
9
|
-
def attributes_for_new_item(data)
|
10
|
-
super(data).tap do |attributes|
|
11
|
-
attributes[:viewer_percentages] = data['viewerPercentages']
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
def eager_load_items_from(items)
|
16
|
-
if included_relationships.include? :viewer_percentages
|
17
|
-
filters = "channel==#{items.map{|item| item['id']}.join(',')}"
|
18
|
-
ids = "contentOwner==#{@auth.owner_name}"
|
19
|
-
conditions = {ids: ids, filters: filters}
|
20
|
-
viewer_percentages = Collections::ViewerPercentages.new auth: @auth
|
21
|
-
viewer_percentages = viewer_percentages.where conditions
|
22
|
-
items.each do |item|
|
23
|
-
item['viewerPercentages'] = viewer_percentages[item['id']]
|
24
|
-
end
|
25
|
-
end
|
26
|
-
super
|
27
|
-
end
|
28
|
-
|
29
9
|
# @private
|
30
10
|
# @note Partnered Channels overwrites +channel_params+ since the query
|
31
11
|
# is slightly different.
|
data/lib/yt/models/base.rb
CHANGED
@@ -7,7 +7,6 @@ require 'yt/associations/has_authentication'
|
|
7
7
|
require 'yt/associations/has_many'
|
8
8
|
require 'yt/associations/has_one'
|
9
9
|
require 'yt/associations/has_reports'
|
10
|
-
require 'yt/associations/has_viewer_percentages'
|
11
10
|
|
12
11
|
require 'yt/errors/request_error'
|
13
12
|
|
@@ -20,7 +19,6 @@ module Yt
|
|
20
19
|
|
21
20
|
include Associations::HasAttribute
|
22
21
|
extend Associations::HasReports
|
23
|
-
extend Associations::HasViewerPercentages
|
24
22
|
extend Associations::HasOne
|
25
23
|
extend Associations::HasMany
|
26
24
|
extend Associations::HasAuthentication
|
data/lib/yt/models/channel.rb
CHANGED
@@ -70,10 +70,6 @@ module Yt
|
|
70
70
|
# @macro has_report
|
71
71
|
has_report :viewer_percentage
|
72
72
|
|
73
|
-
# @deprecated Use {#has_report :viewer_percentage}.
|
74
|
-
# @macro has_viewer_percentages
|
75
|
-
has_viewer_percentages
|
76
|
-
|
77
73
|
# @!attribute [r] statistics_set
|
78
74
|
# @return [Yt::Models::StatisticsSet] the statistics for the video.
|
79
75
|
has_one :statistics_set
|
@@ -107,9 +103,6 @@ module Yt
|
|
107
103
|
if options[:statistics]
|
108
104
|
@statistics_set = StatisticsSet.new data: options[:statistics]
|
109
105
|
end
|
110
|
-
if options[:viewer_percentages]
|
111
|
-
@viewer_percentages = options[:viewer_percentages]
|
112
|
-
end
|
113
106
|
end
|
114
107
|
|
115
108
|
# Returns whether the authenticated account is subscribed to the channel.
|
data/lib/yt/models/policy.rb
CHANGED
@@ -25,11 +25,6 @@ module Yt
|
|
25
25
|
# @return [String] the time the policy was updated.
|
26
26
|
has_attribute :updated_at, type: Time, from: :time_updated
|
27
27
|
|
28
|
-
# @deprecated Use {#updated_at} instead.
|
29
|
-
def time_updated
|
30
|
-
updated_at
|
31
|
-
end
|
32
|
-
|
33
28
|
# @return [Array<PolicyRule>] a list of rules that specify the action
|
34
29
|
# that YouTube should take and may optionally specify the conditions
|
35
30
|
# under which that action is enforced.
|
data/lib/yt/models/video.rb
CHANGED
@@ -79,12 +79,6 @@ module Yt
|
|
79
79
|
status.upload_status == 'uploaded'
|
80
80
|
end
|
81
81
|
|
82
|
-
# @deprecated Use {#uploading?} instead.
|
83
|
-
# @return [Boolean] whether the video is being uploaded to YouTube.
|
84
|
-
def uploaded?
|
85
|
-
uploading?
|
86
|
-
end
|
87
|
-
|
88
82
|
# @return [Boolean] whether the video failed to upload to YouTube because
|
89
83
|
# of an unsupported codec.
|
90
84
|
# @see https://support.google.com/youtube/answer/1722171
|
@@ -439,10 +433,6 @@ module Yt
|
|
439
433
|
# @macro daily_report
|
440
434
|
has_report :monetized_playbacks
|
441
435
|
|
442
|
-
# @deprecated Use {#has_report :viewer_percentage}.
|
443
|
-
# @macro has_viewer_percentages
|
444
|
-
has_viewer_percentages
|
445
|
-
|
446
436
|
### STATISTICS ###
|
447
437
|
|
448
438
|
has_one :statistics_set
|
data/lib/yt/version.rb
CHANGED
@@ -205,11 +205,6 @@ describe Yt::Channel, :device_app do
|
|
205
205
|
expect{channel.impressions_on 3.days.ago}.to raise_error Yt::Errors::Unauthorized
|
206
206
|
end
|
207
207
|
|
208
|
-
# @deprecated, use channel.viewer_percentage instead
|
209
|
-
it 'returns valid reports for channel-related demographics' do
|
210
|
-
expect{channel.viewer_percentages}.not_to raise_error
|
211
|
-
end
|
212
|
-
|
213
208
|
it 'cannot give information about its content owner' do
|
214
209
|
expect{channel.content_owner}.to raise_error Yt::Errors::Forbidden
|
215
210
|
expect{channel.linked_at}.to raise_error Yt::Errors::Forbidden
|
@@ -319,11 +319,6 @@ describe Yt::Video, :device_app do
|
|
319
319
|
expect{video.earnings_on 3.days.ago}.to raise_error Yt::Errors::Unauthorized
|
320
320
|
expect{video.impressions_on 3.days.ago}.to raise_error Yt::Errors::Unauthorized
|
321
321
|
end
|
322
|
-
|
323
|
-
# @deprecated, use video.viewer_percentage instead
|
324
|
-
it 'returns valid reports for video-related demographics' do
|
325
|
-
expect{video.viewer_percentages}.not_to raise_error
|
326
|
-
end
|
327
322
|
end
|
328
323
|
|
329
324
|
# @note: This test is separated from the block above because, for some
|
@@ -977,22 +977,6 @@ describe Yt::Channel, :partner do
|
|
977
977
|
end
|
978
978
|
end
|
979
979
|
|
980
|
-
# @deprecated, use channel.viewer_percentage instead
|
981
|
-
specify 'viewer percentages by gender and age range can be retrieved' do
|
982
|
-
expect(channel.viewer_percentages[:female]['18-24']).to be_a Float
|
983
|
-
expect(channel.viewer_percentages[:female]['25-34']).to be_a Float
|
984
|
-
expect(channel.viewer_percentages[:female]['35-44']).to be_a Float
|
985
|
-
expect(channel.viewer_percentages[:female]['45-54']).to be_a Float
|
986
|
-
expect(channel.viewer_percentages[:female]['55-64']).to be_a Float
|
987
|
-
expect(channel.viewer_percentages[:female]['65-']).to be_a Float
|
988
|
-
expect(channel.viewer_percentages[:male]['18-24']).to be_a Float
|
989
|
-
expect(channel.viewer_percentages[:male]['25-34']).to be_a Float
|
990
|
-
expect(channel.viewer_percentages[:male]['35-44']).to be_a Float
|
991
|
-
expect(channel.viewer_percentages[:male]['45-54']).to be_a Float
|
992
|
-
expect(channel.viewer_percentages[:male]['55-64']).to be_a Float
|
993
|
-
expect(channel.viewer_percentages[:male]['65-']).to be_a Float
|
994
|
-
end
|
995
|
-
|
996
980
|
specify 'information about its content owner can be retrieved' do
|
997
981
|
expect(channel.content_owner).to be_a String
|
998
982
|
expect(channel.linked_at).to be_a Time
|
@@ -12,14 +12,6 @@ describe Yt::ContentOwner, :partner do
|
|
12
12
|
specify '.size', :ruby2 do
|
13
13
|
expect(partnered_channels.size).to be > 0
|
14
14
|
end
|
15
|
-
|
16
|
-
context 'with includes(:viewer_percentages)' do
|
17
|
-
let(:channel) { partnered_channels.includes(:viewer_percentages).first }
|
18
|
-
|
19
|
-
specify 'eager-loads the viewer percentages of each channel' do
|
20
|
-
expect(channel.instance_variable_defined? :@viewer_percentages).to be true
|
21
|
-
end
|
22
|
-
end
|
23
15
|
end
|
24
16
|
|
25
17
|
describe 'claims' do
|
@@ -884,22 +884,6 @@ describe Yt::Video, :partner do
|
|
884
884
|
expect(viewer_percentage.values).to all(be_instance_of Float)
|
885
885
|
end
|
886
886
|
end
|
887
|
-
|
888
|
-
# @deprecated, use video.viewer_percentage instead
|
889
|
-
specify 'viewer percentages by gender and age range can be retrieved' do
|
890
|
-
expect(video.viewer_percentages[:female]['18-24']).to be_a Float
|
891
|
-
expect(video.viewer_percentages[:female]['25-34']).to be_a Float
|
892
|
-
expect(video.viewer_percentages[:female]['35-44']).to be_a Float
|
893
|
-
expect(video.viewer_percentages[:female]['45-54']).to be_a Float
|
894
|
-
expect(video.viewer_percentages[:female]['55-64']).to be_a Float
|
895
|
-
expect(video.viewer_percentages[:female]['65-']).to be_a Float
|
896
|
-
expect(video.viewer_percentages[:male]['18-24']).to be_a Float
|
897
|
-
expect(video.viewer_percentages[:male]['25-34']).to be_a Float
|
898
|
-
expect(video.viewer_percentages[:male]['35-44']).to be_a Float
|
899
|
-
expect(video.viewer_percentages[:male]['45-54']).to be_a Float
|
900
|
-
expect(video.viewer_percentages[:male]['55-64']).to be_a Float
|
901
|
-
expect(video.viewer_percentages[:male]['65-']).to be_a Float
|
902
|
-
end
|
903
887
|
end
|
904
888
|
|
905
889
|
context 'given a video claimable by the authenticated Content Owner' do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yt
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.19.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claudio Baccigalupo
|
@@ -129,7 +129,6 @@ files:
|
|
129
129
|
- lib/yt/associations/has_many.rb
|
130
130
|
- lib/yt/associations/has_one.rb
|
131
131
|
- lib/yt/associations/has_reports.rb
|
132
|
-
- lib/yt/associations/has_viewer_percentages.rb
|
133
132
|
- lib/yt/collections/advertising_options_sets.rb
|
134
133
|
- lib/yt/collections/annotations.rb
|
135
134
|
- lib/yt/collections/assets.rb
|
@@ -165,7 +164,6 @@ files:
|
|
165
164
|
- lib/yt/collections/user_infos.rb
|
166
165
|
- lib/yt/collections/video_categories.rb
|
167
166
|
- lib/yt/collections/videos.rb
|
168
|
-
- lib/yt/collections/viewer_percentages.rb
|
169
167
|
- lib/yt/config.rb
|
170
168
|
- lib/yt/errors/forbidden.rb
|
171
169
|
- lib/yt/errors/missing_auth.rb
|
@@ -284,7 +282,6 @@ files:
|
|
284
282
|
- spec/requests/as_content_owner/ownership_spec.rb
|
285
283
|
- spec/requests/as_content_owner/playlist_spec.rb
|
286
284
|
- spec/requests/as_content_owner/video_spec.rb
|
287
|
-
- spec/requests/as_content_owner/viewer_percentages_spec.rb
|
288
285
|
- spec/requests/as_server_app/channel_spec.rb
|
289
286
|
- spec/requests/as_server_app/playlist_item_spec.rb
|
290
287
|
- spec/requests/as_server_app/playlist_spec.rb
|
@@ -388,7 +385,6 @@ test_files:
|
|
388
385
|
- spec/requests/as_content_owner/ownership_spec.rb
|
389
386
|
- spec/requests/as_content_owner/playlist_spec.rb
|
390
387
|
- spec/requests/as_content_owner/video_spec.rb
|
391
|
-
- spec/requests/as_content_owner/viewer_percentages_spec.rb
|
392
388
|
- spec/requests/as_server_app/channel_spec.rb
|
393
389
|
- spec/requests/as_server_app/playlist_item_spec.rb
|
394
390
|
- spec/requests/as_server_app/playlist_spec.rb
|
@@ -1,40 +0,0 @@
|
|
1
|
-
module Yt
|
2
|
-
module Associations
|
3
|
-
# Provides methods to access the viewer percentage reports of a resource.
|
4
|
-
#
|
5
|
-
# YouTube resources with viewer percentage reports are:
|
6
|
-
# {Yt::Models::Channel channels} and {Yt::Models::Channel videos}.
|
7
|
-
# @deprecated
|
8
|
-
module HasViewerPercentages
|
9
|
-
# @!macro has_viewer_percentages
|
10
|
-
# @deprecated
|
11
|
-
# @!method viewer_percentages
|
12
|
-
# @return [Hash<Symbol,Hash<String,Float>>] the viewer percentages.
|
13
|
-
# The first-level hash identifies the genres (:female, :male).
|
14
|
-
# The second-level hash identifies the age ranges ('18-24',
|
15
|
-
# '25-34', '35-44', '45-54', '55-64', '65-')
|
16
|
-
# @example Return the % of male viewers of a channel older than 64
|
17
|
-
# channel.viewer_percentages[:male]['65-'] #=> 12.02
|
18
|
-
|
19
|
-
# Defines one public instance methods to access the viewer percentages of
|
20
|
-
# a resource for a specific metric.
|
21
|
-
# @example Adds +viewer_percentages+ and +viewer_percentage+ on Channel.
|
22
|
-
# class Channel < Resource
|
23
|
-
# has_viewer_percentages
|
24
|
-
# end
|
25
|
-
def has_viewer_percentages
|
26
|
-
require 'yt/collections/viewer_percentages'
|
27
|
-
|
28
|
-
define_viewer_percentages_method
|
29
|
-
end
|
30
|
-
|
31
|
-
private
|
32
|
-
|
33
|
-
def define_viewer_percentages_method
|
34
|
-
define_method :viewer_percentages do
|
35
|
-
@viewer_percentages ||= Collections::ViewerPercentages.of(self)[id]
|
36
|
-
end
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,56 +0,0 @@
|
|
1
|
-
require 'yt/collections/base'
|
2
|
-
|
3
|
-
module Yt
|
4
|
-
module Collections
|
5
|
-
# @deprecated Use {Yt::Collections::Reports} instead.
|
6
|
-
class ViewerPercentages < Base
|
7
|
-
delegate :[], to: :all
|
8
|
-
|
9
|
-
def all
|
10
|
-
Hash.new{|h,k| h[k] = Hash.new{|h,k| h[k] = Hash.new 0.0}}.tap do |hash|
|
11
|
-
each do |item|
|
12
|
-
hash[item.id][item.gender][item.age_range] = item.value
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
# @note could use column headers to be more precise
|
20
|
-
def new_item(data)
|
21
|
-
Struct.new(:id, :gender, :age_range, :value).new.tap do |item|
|
22
|
-
item.id = data.first
|
23
|
-
item.gender = data.second.to_sym
|
24
|
-
item.age_range = data.third.gsub /^age/, ''
|
25
|
-
item.value = data.last
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def list_params
|
30
|
-
super.tap do |params|
|
31
|
-
params[:path] = '/youtube/analytics/v1/reports'
|
32
|
-
params[:params] = reports_params
|
33
|
-
params[:capitalize_params] = false
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def reports_params
|
38
|
-
{}.tap do |params|
|
39
|
-
params['start-date'] = 3.months.ago.to_date
|
40
|
-
params['end-date'] = Date.today.to_date
|
41
|
-
params['metrics'] = :viewerPercentage
|
42
|
-
params['sort'] = 'gender,ageGroup'
|
43
|
-
params.merge! @parent.reports_params if @parent
|
44
|
-
apply_where_params! params
|
45
|
-
main_dimension = params.fetch(:filters, '').split('==').first
|
46
|
-
main_dimension ||= params.fetch(:ids, '').split('==').first
|
47
|
-
params['dimensions'] = "#{main_dimension},#{params['sort']}"
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def items_key
|
52
|
-
'rows'
|
53
|
-
end
|
54
|
-
end
|
55
|
-
end
|
56
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
require 'spec_helper'
|
3
|
-
require 'yt/collections/viewer_percentages'
|
4
|
-
|
5
|
-
describe Yt::Collections::ViewerPercentages, :partner do
|
6
|
-
subject(:viewer_percentages) { Yt::Collections::ViewerPercentages.new auth: $content_owner }
|
7
|
-
|
8
|
-
context 'for two channels at once' do
|
9
|
-
let(:filters) { 'channel==UCxO1tY8h1AhOz0T4ENwmpow,UCsmvakQZlvGsyjyOhmhvOsw' }
|
10
|
-
let(:ids) { "contentOwner==#{$content_owner.owner_name}" }
|
11
|
-
let(:result) { viewer_percentages.where filters: filters, ids: ids }
|
12
|
-
|
13
|
-
it 'returns the viewer percentages of both' do
|
14
|
-
expect(result['UCggO99g88eUDPcqkTShOPvw'][:female]['18-24']).to be_a Float
|
15
|
-
expect(result['UC8oJ8Sdgkpcy4gylGjTHtBw'][:male]['18-24']).to be_a Float
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|