rss-connector 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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4f8d899ac890065f11c8d6697e5b1b2cf5b5ba61
4
+ data.tar.gz: 361b7655de149538e63c02b5e02749babbb34ce7
5
+ SHA512:
6
+ metadata.gz: 89c51799dc31923adbd7944d5d9cda7dc9f74fb1844190e53311e7043fa5dbdbc6de83cabdf7170fd67e64dfd4cbb143bdcbf091fcd887396b64919135eb4a44
7
+ data.tar.gz: 56e11579fe69c99edf6e450f1946b4ffe8c7c718de779c7f6bc711cedd7863cdcc09d5984899625a7d0b8d168300aedd5586ed8e93194fffa18a65410a10bb90
@@ -0,0 +1,54 @@
1
+ # Shore git prepare-commit-msg hook
2
+ #
3
+ # Autom. prepends git commit messages with ticket type and ticket id based on
4
+ # the current branch name (assuming naming convention has been followed).
5
+ #
6
+ # Naming convention for branches:
7
+ # {ticket type}/{ticket id}-{ticket title in param-case}
8
+ # Ex: feature/COR-42-the-meaning-of-life
9
+ # Ex: chore/BOK-23-refactor-everything
10
+ # Ex: bug/WAC-667-neighbor-of-the-beast
11
+ # Ex: task/COR-668-foo-bar-baz
12
+ #
13
+ # Only applies when using:
14
+ # $ git ci -m "message"
15
+ # $ git ci -F path/to/message.txt
16
+ # $ git ci
17
+ #
18
+ # Except it is a:
19
+ # - merge commit
20
+ # - squash commit
21
+ #
22
+ # Example:
23
+ # assuming current branch name is: feature/COR-1-some-ticket-title
24
+ # $ git commit -m "did some stuff"
25
+ # commit message is now: F [#COR-1] did some stuff
26
+ module Overcommit
27
+ module Hook
28
+ module CommitMsg
29
+ VALID_TICKET_TYPES = %w(feature chore bug task)
30
+
31
+ class AddTicketId < Base
32
+ def run
33
+ branch_name = `git symbolic-ref --short HEAD`
34
+ ticket_type, ticket_id = branch_name.scan(/(\w+)\/(\w+-\d+)/).flatten
35
+ may_apply_hook =
36
+ VALID_TICKET_TYPES.include?(ticket_type) &&
37
+ ticket_id &&
38
+ [nil, 'message'].include?(ARGV[1])
39
+
40
+ if may_apply_hook
41
+ prefix = "#{ticket_type[0].upcase} [##{ticket_id.upcase}] "
42
+ # Skip if commit Ticket ID is already present (this fixes a problem
43
+ # with `git commit --amend`).
44
+ unless commit_message.start_with?(prefix)
45
+ `sed -i.bak -e "1s/^/#{prefix}/" #{commit_message_file}`
46
+ end
47
+ end
48
+
49
+ :pass
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
@@ -0,0 +1,17 @@
1
+ CommitMsg:
2
+ ALL:
3
+ enabled: false
4
+ AddTicketId:
5
+ enabled: true
6
+
7
+ PreCommit:
8
+ RuboCop:
9
+ enabled: true
10
+ command: ['bundle', 'exec', 'rubocop']
11
+ on_warn: 'fail'
12
+
13
+ PrePush:
14
+ RSpec:
15
+ enabled: true
16
+ command: ['bundle', 'exec', 'rspec']
17
+
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
@@ -0,0 +1,5 @@
1
+ AllCops:
2
+ Exclude:
3
+ - 'vendor/**/*'
4
+ - 'contract/**/*'
5
+ - '.git-hooks/**/*'
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.3.0
4
+ before_install: gem install bundler -v 1.10.6
5
+
6
+ language: ruby
7
+ script:
8
+ - bundle exec rubocop
9
+ - bundle exec rake db:migrate
10
+ - bundle exec rspec
11
+
12
+ branches:
13
+ only:
14
+ - "master"
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rss-connector.gemspec
4
+ gemspec
@@ -0,0 +1,27 @@
1
+ # RSS::Connector
2
+
3
+ Talks to RSS.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'rss-connector', git
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install rss-connector
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ Bug reports and pull requests are welcome on GitHub at https://github.com/shore-gmbh/rss-connector.
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,16 @@
1
+ require 'active_support/all'
2
+ require_relative 'rss/config'
3
+ require_relative 'rss/rule'
4
+
5
+ module RSS #:nodoc:
6
+ # Authentication credentials are stored in constants, make sure
7
+ # configuration is set before requiring the connector.
8
+ def self.load!
9
+ if RSS.configuration.base_uri.empty?
10
+ puts 'Missing RSS base_uri config'
11
+ exit
12
+ end
13
+
14
+ require_relative 'rss/connector'
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ module RSS #:nodoc:
2
+ class << self
3
+ attr_accessor :configuration
4
+ end
5
+
6
+ def self.configure
7
+ self.configuration ||= Configuration.new
8
+ yield(configuration)
9
+ end
10
+
11
+ class Configuration #:nodoc:
12
+ attr_accessor :base_uri, :secret
13
+
14
+ def initialize
15
+ @base_uri = 'http://localhost:5000/'
16
+ @secret = ''
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,315 @@
1
+ require 'httparty'
2
+ require 'net/http'
3
+
4
+ module RSS
5
+ # Utility class encapsulating synchronous communication with RSS.
6
+ class Connector # rubocop:disable ClassLength
7
+ include HTTParty
8
+
9
+ base_uri RSS.configuration.base_uri
10
+
11
+ BASIC_AUTH_USERNAME = (RSS.configuration.secret || 'secret').freeze
12
+ BASIC_AUTH_PASSWORD = ''.freeze
13
+ BASIC_AUTH_CREDENTIALS = {
14
+ basic_auth: {
15
+ username: BASIC_AUTH_USERNAME,
16
+ password: BASIC_AUTH_PASSWORD
17
+ }
18
+ }.freeze
19
+
20
+ attr_reader :oid, :scope
21
+
22
+ # @param oid [String] Organziation ID
23
+ # @param scope [String]
24
+ def initialize(oid, scope)
25
+ @oid = oid
26
+ @scope = scope
27
+ end
28
+
29
+ # @param series_id [String]
30
+ # @raise [RuntimeError] RSS request failed
31
+ def get_series(series_id)
32
+ path = "#{base_path}/series/#{series_id}"
33
+ response = self.class.authenticated_get(path)
34
+
35
+ case response.code
36
+ when 200 then JSON.parse(response.body)['series']
37
+ when 404 then nil
38
+ else fail "RSS: 'GET #{path}' failed with status = #{response.code}."
39
+ end
40
+ end
41
+
42
+ # @raise [RuntimeError] RSS request failed
43
+ def create_series(attributes = {})
44
+ path = "#{base_path}/series"
45
+ response = self.class.authenticated_post(
46
+ path, query: prepare_series_attributes(attributes)
47
+ )
48
+
49
+ case response.code
50
+ when 201 then JSON.parse(response.body)
51
+ else fail "RSS: 'POST #{path}' failed with status = #{response.code}."
52
+ end
53
+ end
54
+
55
+ # @raise [RuntimeError] RSS request failed
56
+ def create_or_update_series(series_id, attributes = {})
57
+ path = "#{base_path}/series/#{series_id}"
58
+ response = self.class.authenticated_put(
59
+ path, query: prepare_series_attributes(attributes)
60
+ )
61
+
62
+ case response.code
63
+ when 200, 201 then JSON.parse(response.body)
64
+ else fail "RSS: 'PUT #{path}' failed with status = #{response.code}."
65
+ end
66
+ end
67
+
68
+ # @raise [RuntimeError] RSS request failed
69
+ def update_series(series_id, attributes = {})
70
+ path = "#{base_path}/series/#{series_id}"
71
+ response = self.class.authenticated_patch(
72
+ path, query: prepare_series_attributes(attributes)
73
+ )
74
+
75
+ case response.code
76
+ when 200 then JSON.parse(response.body)
77
+ when 404 then nil
78
+ else fail "RSS: 'PATCH #{path}' failed with status = #{response.code}."
79
+ end
80
+ end
81
+
82
+ # @raise [RuntimeError] RSS request failed
83
+ def delete_series(series_id)
84
+ path = "#{base_path}/series/#{series_id}"
85
+ response = self.class.authenticated_delete(path)
86
+
87
+ case response.code
88
+ when 200 then JSON.parse(response.body)
89
+ when 404 then nil
90
+ else fail "RSS: 'DELETE #{path}' failed with status = #{response.code}."
91
+ end
92
+ end
93
+
94
+ # @raise [RuntimeError] RSS request failed
95
+ def get_rule(rule_id)
96
+ path = "#{base_path}/rules/#{rule_id}"
97
+ response = self.class.authenticated_get(path)
98
+
99
+ case response.code
100
+ when 200 then JSON.parse(response.body)
101
+ when 404 then nil
102
+ else fail "RSS: 'GET #{path}' failed with status = #{response.code}."
103
+ end
104
+ end
105
+
106
+ # @raise [RuntimeError] RSS request failed
107
+ def get_rules(filters = {})
108
+ path = "#{base_path}/rules"
109
+ response = self.class.authenticated_get(
110
+ path, query: sanitize_filters(filters)
111
+ )
112
+
113
+ case response.code
114
+ when 200 then JSON.parse(response.body)['rules']
115
+ when 404 then nil
116
+ else fail "RSS: 'GET #{path}' failed with status = #{response.code}."
117
+ end
118
+ end
119
+
120
+ # @raise [RuntimeError] RSS request failed
121
+ def create_rule(attributes = {})
122
+ path = "#{base_path}/rules"
123
+ response = self.class.authenticated_post(
124
+ path, query: prepare_rule_attributes(attributes)
125
+ )
126
+
127
+ case response.code
128
+ when 201 then JSON.parse(response.body)
129
+ else fail "RSS: 'POST #{path}' failed with status = #{response.code}."
130
+ end
131
+ end
132
+
133
+ # @raise [RuntimeError] RSS request failed
134
+ def create_or_update_rule(rule_id, attributes = {})
135
+ path = "#{base_path}/rules/#{rule_id}"
136
+ response = self.class.authenticated_put(
137
+ path, query: prepare_rule_attributes(attributes)
138
+ )
139
+
140
+ case response.code
141
+ when 200, 201 then JSON.parse(response.body)
142
+ else fail "RSS: 'PUT #{path}' failed with status = #{response.code}."
143
+ end
144
+ end
145
+
146
+ # @raise [RuntimeError] RSS request failed
147
+ def update_rule(rule_id, attributes = {})
148
+ path = "#{base_path}/rules/#{rule_id}"
149
+ response = self.class.authenticated_patch(
150
+ path, query: prepare_rule_attributes(attributes)
151
+ )
152
+
153
+ case response.code
154
+ when 200 then JSON.parse(response.body)
155
+ when 404 then nil
156
+ else fail "RSS: 'PATCH #{path}' failed with status = #{response.code}."
157
+ end
158
+ end
159
+
160
+ # @raise [RuntimeError] RSS request failed
161
+ def delete_rule(rule_id)
162
+ path = "#{base_path}/rules/#{rule_id}"
163
+ response = self.class.authenticated_delete(path)
164
+
165
+ case response.code
166
+ when 200 then JSON.parse(response.body)
167
+ when 404 then nil
168
+ else fail "RSS: 'DELETE #{path}' failed with status = #{response.code}."
169
+ end
170
+ end
171
+
172
+ # @raise [RuntimeError] RSS request failed
173
+ def get_occurrences(filters = {}) # rubocop:disable MethodLength
174
+ path = "#{base_path}/occurrences"
175
+ response = self.class.authenticated_get(
176
+ path, query: sanitize_filters(filters)
177
+ )
178
+
179
+ case response.code
180
+ when 200
181
+ (JSON.parse(response.body)['occurrences'] || []).map do |h|
182
+ build_occurrence_payload(h)
183
+ end
184
+ else fail "RSS: 'GET #{path}' failed with status = #{response.code}."
185
+ end
186
+ end
187
+
188
+ # @param occurrence_id [String]
189
+ # @raise [RuntimeError] RSS request failed
190
+ def get_occurrence(occurrence_id)
191
+ path = "#{base_path}/occurrences/#{occurrence_id}"
192
+ response = self.class.authenticated_get(path)
193
+
194
+ case response.code
195
+ when 200
196
+ occurrence_hash = JSON.parse(response.body)['occurrence']
197
+ build_occurrence_payload(occurrence_hash)
198
+ when 404 then nil
199
+ else fail "RSS: 'GET #{path}' failed with status = #{response.code}."
200
+ end
201
+ end
202
+
203
+ # @param occurrence_id [String]
204
+ # @raise [RuntimeError] RSS request failed
205
+ # rubocop:disable MethodLength
206
+ def update_occurrence(occurrence_id, attributes = {})
207
+ path = "#{base_path}/occurrences/#{occurrence_id}"
208
+ response = self.class.authenticated_patch(
209
+ path, query: prepare_occurrence_attributes(attributes)
210
+ )
211
+
212
+ case response.code
213
+ when 200
214
+ occurrence_hash = JSON.parse(response.body)['occurrence']
215
+ build_occurrence_payload(occurrence_hash)
216
+ when 404 then nil
217
+ else fail "RSS: 'PATCH #{path}' failed with status = #{response.code}."
218
+ end
219
+ end
220
+
221
+ # @param occurrence_id [String]
222
+ # @raise [RuntimeError] RSS request failed
223
+ def delete_occurrence(occurrence_id)
224
+ path = "#{base_path}/occurrences/#{occurrence_id}"
225
+ response = self.class.authenticated_delete(path)
226
+
227
+ case response.code
228
+ when 200 then JSON.parse(response.body)
229
+ when 404 then nil
230
+ else fail "RSS: 'DELETE #{path}' failed with status = #{response.code}."
231
+ end
232
+ end
233
+
234
+ private
235
+
236
+ # Define variants of all HTTParty request methods with authentication
237
+ # support.
238
+ self::Request::SupportedHTTPMethods
239
+ .map { |x| x.name.demodulize.downcase }.each do |method|
240
+ define_singleton_method("authenticated_#{method}") do |path, options = {}|
241
+ send(method, path, options.merge(BASIC_AUTH_CREDENTIALS))
242
+ end
243
+ end
244
+
245
+ def base_path
246
+ "/v1/#{oid}/#{scope}"
247
+ end
248
+
249
+ # @param series_attributes [Hash]
250
+ # @return [Hash]
251
+ def prepare_series_attributes(series_attributes = {})
252
+ (series_attributes || {}).tap do |attributes|
253
+ attributes[:rules] ||= []
254
+
255
+ attributes[:rules].map! do |rule_attributes|
256
+ prepare_rule_attributes(rule_attributes, series_attributes)
257
+ end
258
+ end
259
+ end
260
+
261
+ # @param rule_attributes [Hash]
262
+ # @return [Hash]
263
+ def prepare_rule_attributes(rule_attributes = {}, series_attributes = nil)
264
+ {}.tap do |attrs|
265
+ rule = Rule.new(rule_attributes)
266
+
267
+ attrs[:id] = rule.id # core is always creating the rule id now
268
+ attrs[:recurrence] = rule.recurrence
269
+
270
+ if series_attributes
271
+ attrs[:duration] = series_attributes[:duration] || rule.duration
272
+ attrs[:time_zone] = series_attributes[:time_zone]
273
+ end
274
+ end
275
+ end
276
+
277
+ # @param occurrence_attributes [Hash]
278
+ # @return [Hash]
279
+ def prepare_occurrence_attributes(occurrence_attributes = {})
280
+ {}.tap do |attrs|
281
+ if occurrence_attributes[:starts_at].present?
282
+ attrs[:starts_at] = iso8601_param(occurrence_attributes[:starts_at])
283
+ end
284
+
285
+ if occurrence_attributes[:ends_at].present?
286
+ attrs[:ends_at] = iso8601_param(occurrence_attributes[:ends_at])
287
+ end
288
+ end
289
+ end
290
+
291
+ def sanitize_filters(filters = {})
292
+ filters.tap do |f|
293
+ if f[:interval_starts_at].present?
294
+ f[:interval_starts_at] = iso8601_param(f[:interval_starts_at])
295
+ end
296
+
297
+ if f[:interval_ends_at].present?
298
+ f[:interval_ends_at] = iso8601_param(f[:interval_ends_at])
299
+ end
300
+ end
301
+ end
302
+
303
+ def iso8601_param(p)
304
+ p.respond_to?(:iso8601) ? p.iso8601 : p.to_s
305
+ end
306
+
307
+ # @param occurrence_hash [Hash]
308
+ def build_occurrence_payload(occurrence_hash)
309
+ occurrence_hash.tap do |p|
310
+ p['starts_at'] = Time.zone.parse(p['starts_at']) if p['starts_at']
311
+ p['ends_at'] = Time.zone.parse(p['ends_at']) if p['ends_at']
312
+ end if occurrence_hash
313
+ end
314
+ end
315
+ end
@@ -0,0 +1,130 @@
1
+ module RSS
2
+ # Class to build and compare RSS Rules.
3
+ class Rule
4
+ attr_reader :recurrence
5
+
6
+ def initialize(attributes = {})
7
+ @recurrence = {}
8
+
9
+ self.id = SecureRandom.uuid
10
+ self.attributes = attributes
11
+ end
12
+
13
+ # getters
14
+ attr_reader :id, :duration
15
+
16
+ def starts_at
17
+ @recurrence[:starts_at]
18
+ end
19
+
20
+ def ends_at
21
+ @recurrence[:ends_at]
22
+ end
23
+
24
+ def count
25
+ @recurrence[:count]
26
+ end
27
+
28
+ def frequency
29
+ @recurrence[:frequency] || 'daily'
30
+ end
31
+
32
+ def interval
33
+ @recurrence[:interval] || 1
34
+ end
35
+
36
+ def attributes
37
+ {}.tap do |a|
38
+ a[:id] = id
39
+ a[:recurrence] = @recurrence.stringify_keys
40
+ a[:duration] = @duration if @duration
41
+ end
42
+ end
43
+
44
+ def convert_date(t)
45
+ t = t.is_a?(String) ? Time.zone.parse(t) : t
46
+ return if t.nil?
47
+ t.utc.iso8601
48
+ end
49
+
50
+ # setters
51
+ def id=(id)
52
+ @id = id.to_s
53
+ end
54
+
55
+ def count=(c)
56
+ @recurrence[:count] = c
57
+ end
58
+
59
+ def frequency=(f)
60
+ @recurrence[:frequency] = f.to_s
61
+ end
62
+
63
+ def interval=(i)
64
+ @recurrence[:interval] = i.to_i
65
+ end
66
+
67
+ def starts_at=(t)
68
+ @recurrence[:starts_at] = convert_date(t)
69
+ end
70
+
71
+ def ends_at=(t)
72
+ @recurrence[:ends_at] = convert_date(t)
73
+ end
74
+
75
+ def duration=(d)
76
+ @duration = d.to_i
77
+ end
78
+
79
+ def recurrence=(r)
80
+ if r.is_a?(Hash)
81
+ self.attributes = r
82
+ else
83
+ fail "recurrence= can only receive a Hash. Received #{r.class}"
84
+ end
85
+ end
86
+
87
+ def attributes=(attributes = {})
88
+ attributes.each_pair do |attr, value|
89
+ if respond_to?(assign = "#{attr}=")
90
+ send(assign, value)
91
+ end
92
+ end
93
+ end
94
+
95
+ # @return JSON string
96
+ def as_json(_options = nil)
97
+ # when on rails 4 use deep stringify keys
98
+ attributes.stringify_keys
99
+ end
100
+
101
+ # Tell wether +self+ is an one-off +Rule+ or not. +self+ is considered to be
102
+ # one-off if and only if it evaluates to a single occurrence.
103
+ #
104
+ # @return [true] if +self+ is a one-off +Rule+. This is 100% reliable.
105
+ # @return [false] if +self+ looks like it is not an one-off +Rule+. This is
106
+ # not 100% reliable. Unfortunately, there is no obvious way to tell for
107
+ # sure if +self+ evaluates to multple occurrences or not.
108
+ def one_off?
109
+ # TODO@cs: There are various problematic edge-cases in the system, because
110
+ # +#one_off?+ is not 100% reliable. We have to fix this ASAP.
111
+ count == 1 || starts_at == ends_at
112
+ end
113
+
114
+ # @return [Array of Rule Objects]
115
+ def self.load(value)
116
+ parsed = JSON.load(value)
117
+ parsed.is_a?(Array) ? parsed.map { |p| new(p) } : []
118
+ end
119
+
120
+ def ==(other)
121
+ as_json == other.as_json
122
+ end
123
+
124
+ # @return JSON string of rules
125
+ def self.dump(rules)
126
+ value = rules.is_a?(Array) ? rules.map(&:as_json) : []
127
+ JSON.dump(value)
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,3 @@
1
+ module RSS
2
+ VERSION = '0.1.0'.freeze
3
+ end
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rss/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'rss-connector'
8
+ spec.version = RSS::VERSION
9
+ spec.authors = ['Dylan Johnston']
10
+ spec.email = ['dylan.johnston@shore.com']
11
+
12
+ spec.summary = 'Connector for RSS'
13
+ spec.description = 'Easy access to RSS and its data.'
14
+ spec.homepage = 'http://shore.com'
15
+ spec.license = 'Proprietary'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features)/})
19
+ end
20
+
21
+ spec.bindir = 'exe'
22
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
23
+ spec.require_paths = ['lib']
24
+
25
+ spec.add_dependency 'httparty', '~> 0.10.2'
26
+ spec.add_dependency 'activesupport', '> 3.0'
27
+
28
+ spec.add_development_dependency 'bundler', '~> 1.10'
29
+ spec.add_development_dependency 'rake', '~> 10.0'
30
+ spec.add_development_dependency 'rspec'
31
+ spec.add_development_dependency 'simplecov', '>= 0.10'
32
+ spec.add_development_dependency 'rubocop', '>= 0.35.1'
33
+ spec.add_development_dependency 'overcommit', '>= 0.29.1'
34
+ spec.add_development_dependency 'pry-byebug'
35
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rss-connector
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Dylan Johnston
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2016-01-27 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.10.2
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.10.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: activesupport
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: simplecov
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0.10'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0.10'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: 0.35.1
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: 0.35.1
111
+ - !ruby/object:Gem::Dependency
112
+ name: overcommit
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: 0.29.1
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: 0.29.1
125
+ - !ruby/object:Gem::Dependency
126
+ name: pry-byebug
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Easy access to RSS and its data.
140
+ email:
141
+ - dylan.johnston@shore.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".git-hooks/commit_msg/add_ticket_id.rb"
147
+ - ".gitignore"
148
+ - ".overcommit.yml"
149
+ - ".rspec"
150
+ - ".rubocop.yml"
151
+ - ".travis.yml"
152
+ - Gemfile
153
+ - README.md
154
+ - Rakefile
155
+ - lib/rss.rb
156
+ - lib/rss/config.rb
157
+ - lib/rss/connector.rb
158
+ - lib/rss/rule.rb
159
+ - lib/rss/version.rb
160
+ - rss-connector.gemspec
161
+ homepage: http://shore.com
162
+ licenses:
163
+ - Proprietary
164
+ metadata: {}
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - ">="
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubyforge_project:
181
+ rubygems_version: 2.4.5
182
+ signing_key:
183
+ specification_version: 4
184
+ summary: Connector for RSS
185
+ test_files: []