weathercli 0.2.0 → 0.5.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/Rakefile +1 -1
- data/VERSION +1 -1
- data/bin/weather +3 -25
- data/lib/weathercli.rb +1 -0
- data/lib/weathercli/cli.rb +39 -0
- data/lib/weathercli/weather.rb +19 -7
- data/spec/cli_spec.rb +55 -0
- data/spec/weather_spec.rb +61 -23
- data/weathercli.gemspec +6 -4
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: cbf5af73f2cb6c2d22aa3534f88d903ab2c0e0a8
|
4
|
+
data.tar.gz: 68d0de76d757a9d9d484f1a2777f61ca22ab1a0b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b8871a1315684f45a4e5a8994bc853615d926ab8234f68989eb4c9552e7696bb8dc41b1dc125b20a212a025be86fab5509bc76ca1e42fdfd9c5a963cf760ed38
|
7
|
+
data.tar.gz: 46d854b1d7752fd7528c151a9c7a184adcc693a7b90efb64271c687fb85ecd2ecf57b5dd5aecca57dda2245690b86c817bc3fd395c9db273c9fdd6eb7765828b
|
data/Rakefile
CHANGED
@@ -19,7 +19,7 @@ Jeweler::Tasks.new do |gem|
|
|
19
19
|
gem.homepage = "http://gitlab.com/kmcq/weathercli"
|
20
20
|
gem.license = "MIT"
|
21
21
|
gem.summary = "Weather updates on the command line."
|
22
|
-
gem.description = "weathercli asks Yahoo for the current weather a few forecasts. You can have a default location or specify one when calling it."
|
22
|
+
gem.description = "weathercli asks Yahoo for the current weather and a few forecasts. You can have a default location or specify one when calling it."
|
23
23
|
gem.authors = ["kmcq"]
|
24
24
|
# dependencies defined in Gemfile
|
25
25
|
end
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.5.0
|
data/bin/weather
CHANGED
@@ -1,28 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
require 'weathercli'
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
File.open(CONFIG_FILE, 'w').write(location)
|
8
|
-
end
|
9
|
-
|
10
|
-
def location
|
11
|
-
location_args = ARGV.join unless ARGV.empty?
|
12
|
-
if location_args
|
13
|
-
print "Save as default location? [y/n]: "
|
14
|
-
if STDIN.gets.chomp.downcase == 'y'
|
15
|
-
save_default_location(location_args)
|
16
|
-
end
|
17
|
-
location_args
|
18
|
-
elsif File.file?(CONFIG_FILE)
|
19
|
-
File.read(CONFIG_FILE)
|
20
|
-
else
|
21
|
-
print "Add default location [e.g. San Francisco, CA]: "
|
22
|
-
location = gets
|
23
|
-
save_default_location(location)
|
24
|
-
location
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
puts WeatherCli::Weather.new(location)
|
4
|
+
weather = WeatherCli::Weather.new(WeatherCli::Cli.location)
|
5
|
+
weather.get_weather
|
6
|
+
puts weather
|
data/lib/weathercli.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
module WeatherCli
|
2
|
+
|
3
|
+
module Cli
|
4
|
+
module_function
|
5
|
+
|
6
|
+
def location
|
7
|
+
if location_args
|
8
|
+
print "Save as default location? [y/n]: "
|
9
|
+
if user_input.downcase == 'y'
|
10
|
+
save_default_location(location_args)
|
11
|
+
end
|
12
|
+
location_args
|
13
|
+
elsif File.file?(config_file)
|
14
|
+
File.read(config_file)
|
15
|
+
else
|
16
|
+
print "Add default location [e.g. San Francisco, CA]: "
|
17
|
+
location = user_input
|
18
|
+
save_default_location(location)
|
19
|
+
location
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def config_file
|
24
|
+
File.join(Dir.home, ".weathercli")
|
25
|
+
end
|
26
|
+
|
27
|
+
def save_default_location(location)
|
28
|
+
File.open(config_file, 'w').write(location)
|
29
|
+
end
|
30
|
+
|
31
|
+
def user_input
|
32
|
+
STDIN.gets.chomp
|
33
|
+
end
|
34
|
+
|
35
|
+
def location_args
|
36
|
+
ARGV.join unless ARGV.empty?
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/weathercli/weather.rb
CHANGED
@@ -6,11 +6,12 @@ module WeatherCli
|
|
6
6
|
attr_reader :location, :conditions, :options, :title, :forecasts
|
7
7
|
|
8
8
|
def initialize(location, *options)
|
9
|
+
@location = location
|
9
10
|
@options = Hash[options.map { |o| [o, true] }]
|
10
|
-
get_weather(location)
|
11
11
|
end
|
12
12
|
|
13
13
|
def to_s
|
14
|
+
return '' unless title && conditions && forecasts
|
14
15
|
todays_forecast = forecasts.first
|
15
16
|
tomorrows_forecast = forecasts.last
|
16
17
|
[
|
@@ -21,14 +22,17 @@ module WeatherCli
|
|
21
22
|
].join("\n")
|
22
23
|
end
|
23
24
|
|
24
|
-
|
25
|
-
|
26
|
-
def get_weather(location)
|
27
|
-
query = construct_query(location)
|
25
|
+
def get_weather
|
26
|
+
query = construct_query(@location)
|
28
27
|
url = construct_url(query)
|
29
|
-
|
28
|
+
results = retrieve_api_results(url)
|
29
|
+
if results
|
30
|
+
parse_api_results(results)
|
31
|
+
end
|
30
32
|
end
|
31
33
|
|
34
|
+
private
|
35
|
+
|
32
36
|
def construct_query(location)
|
33
37
|
"select * from weather.forecast where woeid in (select woeid from geo.places(1) where text=\"#{location}\")"
|
34
38
|
end
|
@@ -41,7 +45,15 @@ module WeatherCli
|
|
41
45
|
end
|
42
46
|
|
43
47
|
def retrieve_api_results(url)
|
44
|
-
|
48
|
+
begin
|
49
|
+
results_hash = JSON.parse(Net::HTTP::get(URI.parse(url)))
|
50
|
+
raise unless results_hash['query'] && results_hash['query']['results']
|
51
|
+
rescue => _
|
52
|
+
$stderr.puts 'Sorry, something went wrong.'
|
53
|
+
return false
|
54
|
+
else
|
55
|
+
results_hash['query']['results']['channel']['item']
|
56
|
+
end
|
45
57
|
end
|
46
58
|
|
47
59
|
def parse_api_results(results)
|
data/spec/cli_spec.rb
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe WeatherCli::Cli do
|
4
|
+
before { allow(subject).to receive(:save_default_location).and_return(true) }
|
5
|
+
|
6
|
+
context '::location' do
|
7
|
+
let(:location_string) { 'San Francisco, CA' }
|
8
|
+
|
9
|
+
|
10
|
+
context 'when there are arguments' do
|
11
|
+
before do
|
12
|
+
allow(subject).to receive(:location_args).and_return(location_string)
|
13
|
+
allow(subject).to receive(:user_input).and_return('no')
|
14
|
+
allow($stdout).to receive(:write)
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'should return the arguments' do
|
18
|
+
expect(subject.location).to eq(location_string)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when there are no arguments' do
|
23
|
+
context 'and a default file' do
|
24
|
+
before do
|
25
|
+
allow(subject).to receive(:config_file).and_return('a_file_name')
|
26
|
+
allow(File).to receive(:file?).and_return(true)
|
27
|
+
allow(File).to receive(:read).and_return(location_string)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'should return the default file contents' do
|
31
|
+
expect(File).to receive(:read).with('a_file_name')
|
32
|
+
expect(subject.location).to eq(location_string)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'and no default file' do
|
37
|
+
before do
|
38
|
+
allow(subject).to receive(:config_file).and_return('not_a_real_file')
|
39
|
+
allow(subject).to receive(:user_input).and_return('new default locale')
|
40
|
+
end
|
41
|
+
|
42
|
+
it 'should ask for a default location' do
|
43
|
+
add_default_message = "Add default location [e.g. San Francisco, CA]: "
|
44
|
+
expect { subject.location }.to output(add_default_message).to_stdout
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should save the default location' do
|
48
|
+
allow($stdout).to receive(:write)
|
49
|
+
expect(subject).to receive(:save_default_location).with('new default locale')
|
50
|
+
subject.location
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
data/spec/weather_spec.rb
CHANGED
@@ -30,41 +30,81 @@ describe WeatherCli::Weather do
|
|
30
30
|
}
|
31
31
|
}
|
32
32
|
|
33
|
-
|
34
|
-
|
33
|
+
context '#initialize' do
|
34
|
+
it 'should map any options to a truthy hash' do
|
35
|
+
expect(weather.options).to eq({'option1' => true, 'option2' => true})
|
36
|
+
end
|
35
37
|
end
|
36
38
|
|
37
|
-
|
39
|
+
it 'should construct the correct query' do
|
40
|
+
expect(weather.send(:construct_query, location)).to eq(correct_query)
|
41
|
+
end
|
38
42
|
|
39
|
-
|
40
|
-
|
41
|
-
|
43
|
+
it 'should construct the correct URL' do
|
44
|
+
encoded_location = URI.encode(location)
|
45
|
+
correct_url = "https://query.yahooapis.com/v1/public/yql?q=select%20*%20from%20weather.forecast%20where%20woeid%20in%20(select%20woeid%20from%20geo.places(1)%20where%20text%3D%22#{encoded_location}%22)&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys"
|
46
|
+
expect(weather.send(:construct_url, correct_query)).to eq(correct_url)
|
47
|
+
end
|
42
48
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
49
|
+
context '#get_weather' do
|
50
|
+
context 'with a successful api call' do
|
51
|
+
before do
|
52
|
+
allow_any_instance_of(WeatherCli::Weather).to receive(:retrieve_api_results).and_return(api_results)
|
53
|
+
weather.get_weather
|
54
|
+
end
|
48
55
|
|
49
|
-
|
50
|
-
|
51
|
-
|
56
|
+
it 'should have a title' do
|
57
|
+
expect(weather.title).to eq(title)
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'should have the current condition' do
|
61
|
+
expect(weather.conditions).to eq(conditions)
|
62
|
+
end
|
52
63
|
|
53
|
-
|
54
|
-
|
64
|
+
it 'should have the forecast for today and tomorrow' do
|
65
|
+
expect(weather.forecasts.length).to eq(2)
|
66
|
+
expect(weather.forecasts).to eq(forecasts)
|
67
|
+
end
|
55
68
|
end
|
56
69
|
|
57
|
-
|
58
|
-
|
59
|
-
|
70
|
+
context 'with an unsuccessful api call' do
|
71
|
+
before do
|
72
|
+
allow_any_instance_of(WeatherCli::Weather).to receive(:retrieve_api_results).and_return(false)
|
73
|
+
weather.get_weather
|
74
|
+
end
|
75
|
+
|
76
|
+
it 'should not set the weather attributes' do
|
77
|
+
[:title, :conditions, :forecasts].each do |attr|
|
78
|
+
expect(weather.send(attr)).to eq(nil)
|
79
|
+
end
|
80
|
+
end
|
60
81
|
end
|
82
|
+
end
|
61
83
|
|
62
|
-
|
63
|
-
|
84
|
+
describe '#retrieve_api_results' do
|
85
|
+
context 'with a failure' do
|
86
|
+
let(:url) { 'fake_url.fake' }
|
87
|
+
|
88
|
+
before do
|
89
|
+
allow(JSON).to receive(:parse).and_raise(StandardError)
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'should apologize' do
|
93
|
+
expect { weather.send(:retrieve_api_results, url) }.to output("Sorry, something went wrong.\n").to_stderr
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should return false' do
|
97
|
+
allow($stderr).to receive(:write)
|
98
|
+
expect(weather.send(:retrieve_api_results, url)).to eq(false)
|
99
|
+
end
|
64
100
|
end
|
65
101
|
end
|
66
102
|
|
67
103
|
context '#to_s' do
|
104
|
+
before do
|
105
|
+
allow_any_instance_of(WeatherCli::Weather).to receive(:retrieve_api_results).and_return(api_results)
|
106
|
+
weather.get_weather
|
107
|
+
end
|
68
108
|
|
69
109
|
it 'should print out the weather nicely' do
|
70
110
|
output_string = [
|
@@ -75,7 +115,5 @@ describe WeatherCli::Weather do
|
|
75
115
|
].join("\n")
|
76
116
|
expect(weather.to_s).to eq(output_string)
|
77
117
|
end
|
78
|
-
|
79
118
|
end
|
80
|
-
|
81
119
|
end
|
data/weathercli.gemspec
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
# DO NOT EDIT THIS FILE DIRECTLY
|
3
3
|
# Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
|
-
# stub: weathercli 0.
|
5
|
+
# stub: weathercli 0.5.0 ruby lib
|
6
6
|
|
7
7
|
Gem::Specification.new do |s|
|
8
8
|
s.name = "weathercli"
|
9
|
-
s.version = "0.
|
9
|
+
s.version = "0.5.0"
|
10
10
|
|
11
11
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
12
12
|
s.require_paths = ["lib"]
|
13
13
|
s.authors = ["kmcq"]
|
14
|
-
s.date = "2015-01-
|
15
|
-
s.description = "weathercli asks Yahoo for the current weather a few forecasts. You can have a default location or specify one when calling it."
|
14
|
+
s.date = "2015-01-30"
|
15
|
+
s.description = "weathercli asks Yahoo for the current weather and a few forecasts. You can have a default location or specify one when calling it."
|
16
16
|
s.executables = ["weather"]
|
17
17
|
s.extra_rdoc_files = [
|
18
18
|
"README.md"
|
@@ -25,8 +25,10 @@ Gem::Specification.new do |s|
|
|
25
25
|
"VERSION",
|
26
26
|
"bin/weather",
|
27
27
|
"lib/weathercli.rb",
|
28
|
+
"lib/weathercli/cli.rb",
|
28
29
|
"lib/weathercli/weather.rb",
|
29
30
|
"license.md",
|
31
|
+
"spec/cli_spec.rb",
|
30
32
|
"spec/spec_helper.rb",
|
31
33
|
"spec/weather_spec.rb",
|
32
34
|
"weathercli.gemspec"
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: weathercli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- kmcq
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-01-
|
11
|
+
date: 2015-01-30 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -52,8 +52,8 @@ dependencies:
|
|
52
52
|
- - '='
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: 2.0.1
|
55
|
-
description: weathercli asks Yahoo for the current weather a few forecasts. You
|
56
|
-
have a default location or specify one when calling it.
|
55
|
+
description: weathercli asks Yahoo for the current weather and a few forecasts. You
|
56
|
+
can have a default location or specify one when calling it.
|
57
57
|
email:
|
58
58
|
executables:
|
59
59
|
- weather
|
@@ -68,8 +68,10 @@ files:
|
|
68
68
|
- VERSION
|
69
69
|
- bin/weather
|
70
70
|
- lib/weathercli.rb
|
71
|
+
- lib/weathercli/cli.rb
|
71
72
|
- lib/weathercli/weather.rb
|
72
73
|
- license.md
|
74
|
+
- spec/cli_spec.rb
|
73
75
|
- spec/spec_helper.rb
|
74
76
|
- spec/weather_spec.rb
|
75
77
|
- weathercli.gemspec
|