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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5d4382e8b6b054419cb4f627c5d59260220e68d0
4
- data.tar.gz: f45a6dca7648a0c0678d9b4c965dcafc3825a0e9
3
+ metadata.gz: cbf5af73f2cb6c2d22aa3534f88d903ab2c0e0a8
4
+ data.tar.gz: 68d0de76d757a9d9d484f1a2777f61ca22ab1a0b
5
5
  SHA512:
6
- metadata.gz: ab2b19f5541792886c38e4e6650da8f222afb3312df7013d7bc557ac1f57391dd5f3ba5c6d045be404d204cd127d9505b393fe910148ddfd4be77cf77157f6f1
7
- data.tar.gz: 1632b5f36ece5b43e74e4c98fbd075ae8ad7da50418938368591675d50c77c1458868166022f5b34e4a77ea9a936554f44e7dc67c53a5a29ff86fa5eacfbf05d
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.2.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
- CONFIG_FILE = File.join(Dir.home, ".weathercli")
5
-
6
- def save_default_location(location)
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
@@ -1 +1,2 @@
1
1
  require 'weathercli/weather.rb'
2
+ require 'weathercli/cli.rb'
@@ -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
@@ -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
- private
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
- parse_api_results(retrieve_api_results(url))
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
- JSON.parse(Net::HTTP::get(URI.parse(url)))['query']['results']['channel']['item']
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
- before do
34
- allow_any_instance_of(WeatherCli::Weather).to receive(:retrieve_api_results).and_return(api_results)
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
- context '#initialize' do
39
+ it 'should construct the correct query' do
40
+ expect(weather.send(:construct_query, location)).to eq(correct_query)
41
+ end
38
42
 
39
- it 'should construct the correct query' do
40
- expect(weather.send(:construct_query, location)).to eq(correct_query)
41
- end
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
- 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
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
- it 'should have a title' do
50
- expect(weather.title).to eq(title)
51
- end
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
- it 'should have the current condition' do
54
- expect(weather.conditions).to eq(conditions)
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
- it 'should have the forecast for today and tomorrow' do
58
- expect(weather.forecasts.length).to eq(2)
59
- expect(weather.forecasts).to eq(forecasts)
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
- it 'should map any options to a truthy hash' do
63
- expect(weather.options).to eq({'option1' => true, 'option2' => true})
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.2.0 ruby lib
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.2.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-25"
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.2.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-25 00:00:00.000000000 Z
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 can
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