rhn 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ Yjg1OWY2MWU0Y2VjZGY1NWIyOTI5ZThmZDIxMTQzNjhmMTY1YzViNQ==
5
+ data.tar.gz: !binary |-
6
+ NDg0MDU3NzBlZjQzM2JlNjNiODhiNjFlZmY4YThhZWFiOTc5YjFhNg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ Njk0N2NjODhkZmZjY2ZlMWYwM2QzOGE3OGFmYzVhZWZkNWZlNmM3Mzc4M2Jm
10
+ MTM3Zjc2OTlmYjI3MTk2ZjRhOWZkNTQ4M2M5YjA2ODY5ZjQxYTc2N2Q3YjQw
11
+ ZDFiNzgyNTFmMDFlNWNhZmEyZWRkYmNiM2U4NjVhNjY4NjE4ZjE=
12
+ data.tar.gz: !binary |-
13
+ OGMzNDc0NDY2M2QzMWJkZTRkZDc3YjRkYzdjZGQzZDJjYjA4ZTMxNzYyYThl
14
+ ODc1MWU3OTU5ODk5YjRiOGU4OGE0MzUxYTRhNDA2ZDNiOThiNTk1OTgzZjZi
15
+ MjZjYWExMDgxN2Y5NTJmYTYxMjc3YTVkYjQ4YzZjZjZiMjFjZTU=
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in rhn.gemspec
4
+ gemspec
data/Gemfile.lock ADDED
@@ -0,0 +1,75 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rhn (0.0.3)
5
+ json
6
+ ruby-hackernews
7
+ sinatra
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ bump (0.4.2)
13
+ columnize (0.3.6)
14
+ debugger (1.6.1)
15
+ columnize (>= 0.3.1)
16
+ debugger-linecache (~> 1.2.0)
17
+ debugger-ruby_core_source (~> 1.2.3)
18
+ debugger-linecache (1.2.0)
19
+ debugger-ruby_core_source (1.2.3)
20
+ diff-lcs (1.2.4)
21
+ domain_name (0.5.9)
22
+ unf (>= 0.0.5, < 1.0.0)
23
+ json (1.8.0)
24
+ mechanize (2.6.0)
25
+ domain_name (~> 0.5, >= 0.5.1)
26
+ mime-types (~> 1.17, >= 1.17.2)
27
+ net-http-digest_auth (~> 1.1, >= 1.1.1)
28
+ net-http-persistent (~> 2.5, >= 2.5.2)
29
+ nokogiri (~> 1.4)
30
+ ntlm-http (~> 0.1, >= 0.1.1)
31
+ webrobots (>= 0.0.9, < 0.2)
32
+ mime-types (1.24)
33
+ mini_portile (0.5.1)
34
+ net-http-digest_auth (1.2.1)
35
+ net-http-persistent (2.8)
36
+ nokogiri (1.6.0)
37
+ mini_portile (~> 0.5.0)
38
+ ntlm-http (0.1.1)
39
+ rack (1.5.2)
40
+ rack-protection (1.5.0)
41
+ rack
42
+ rack-test (0.6.2)
43
+ rack (>= 1.0)
44
+ require_all (1.2.1)
45
+ rspec (2.14.1)
46
+ rspec-core (~> 2.14.0)
47
+ rspec-expectations (~> 2.14.0)
48
+ rspec-mocks (~> 2.14.0)
49
+ rspec-core (2.14.5)
50
+ rspec-expectations (2.14.2)
51
+ diff-lcs (>= 1.1.3, < 2.0)
52
+ rspec-mocks (2.14.3)
53
+ ruby-hackernews (1.3.3)
54
+ mechanize (>= 1.0.0)
55
+ require_all (>= 1.1.0)
56
+ sinatra (1.4.3)
57
+ rack (~> 1.4)
58
+ rack-protection (~> 1.4)
59
+ tilt (~> 1.3, >= 1.3.4)
60
+ tilt (1.4.1)
61
+ unf (0.1.1)
62
+ unf_ext
63
+ unf_ext (0.0.6)
64
+ webrobots (0.1.1)
65
+
66
+ PLATFORMS
67
+ ruby
68
+
69
+ DEPENDENCIES
70
+ bump
71
+ bundler (~> 1.3)
72
+ debugger
73
+ rack-test
74
+ rhn!
75
+ rspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Lincoln de Sousa
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Makefile ADDED
@@ -0,0 +1,7 @@
1
+ all:
2
+ @echo "Step 1. Checking dependencies"
3
+ @bundle install && echo "Ok"
4
+ @echo "\n"
5
+
6
+ @echo "Step 2. Running tests"
7
+ @rspec -d -c -f d
data/README.md ADDED
@@ -0,0 +1,45 @@
1
+ # RHN
2
+
3
+ Yet another WEB API for hackernews. Beware of lazy hack ahead!
4
+ This project is a very thin layer on top of [ruby-hackernews](https://github.com/bolthar/ruby-hackernews) so
5
+ we can access this info through HTTP.
6
+
7
+ The main usage of this API is an [Emacs Client for Hackernews](https://github.com/clarete/hackernews.el).
8
+
9
+ ## Install and Run
10
+
11
+ That's easy. You just have to get the code and run the `rhn` executable:
12
+
13
+ $ gem install rhn
14
+
15
+ Boom! Just change your emacs configuration adding the following lines:
16
+
17
+ (setq hackernews-url "http://127.0.0.1:4567/")
18
+
19
+ The next time you run `M-x hackernews` you'll be using your local proxy.
20
+
21
+ ## As a library
22
+
23
+ Add this line to your application's Gemfile
24
+
25
+ gem 'rhn'
26
+
27
+ And then execute
28
+
29
+ $ bundle
30
+
31
+ ## Usage
32
+
33
+ $ rhn
34
+
35
+ Then open a browser and try the following URL:
36
+
37
+ http://localhost:4567/api/?r=%7B%22symbol%22%3A%22HN.hotpage%22%7D
38
+
39
+ ## Contributing
40
+
41
+ 1. Fork it
42
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
43
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
44
+ 4. Push to the branch (`git push origin my-new-feature`)
45
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require "bundler/setup"
2
+ require "bundler/gem_tasks"
3
+ require "bump/tasks"
data/bin/rhn ADDED
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $:.unshift(File.dirname(__FILE__) + '/../lib') unless $:.include?(File.dirname(__FILE__) + '/../lib')
4
+
5
+ require 'rhn/app'
6
+
7
+ RHN.run!
data/config.ru ADDED
@@ -0,0 +1,6 @@
1
+ # -*- Ruby -*-
2
+
3
+ $LOAD_PATH << "#{File.expand_path "../", __FILE__}/lib"
4
+
5
+ require 'rhn/app'
6
+ run RHN.new
data/lib/rhn/apigen.rb ADDED
@@ -0,0 +1,62 @@
1
+ module ApiGen
2
+
3
+ class AccessDenied < Exception
4
+ end
5
+
6
+ class NotFound < Exception
7
+ end
8
+
9
+ class Entry
10
+ attr_accessor :factory, :symbols
11
+
12
+ def initialize
13
+ @factory = nil
14
+ @symbols = []
15
+ end
16
+ end
17
+
18
+
19
+ class AccessManager
20
+
21
+ @@REGISTRY = {}
22
+
23
+ def self.register factory, symbol
24
+ entry = Entry.new
25
+ entry.factory = factory
26
+ entry.symbols.push symbol
27
+
28
+ @@REGISTRY[factory.name] = entry
29
+ end
30
+
31
+ def self.get name
32
+ @@REGISTRY[name]
33
+ end
34
+ end
35
+
36
+
37
+ class Resolver
38
+ attr_accessor :symbol
39
+
40
+ def initialize symbol
41
+ @symbol = symbol
42
+ end
43
+
44
+ def v *args
45
+ base, subpath = @symbol.split '.'
46
+
47
+ entry = AccessManager.get base
48
+ raise NotFound, "There's no such object" if entry.nil?
49
+
50
+ found = entry.symbols.include?(subpath)
51
+ raise AccessDenied, "You don't have access to this resource" if not found
52
+
53
+ inst = entry.factory.new
54
+ inst.send subpath.to_sym, *args
55
+ end
56
+ end
57
+
58
+ def from_dsl description
59
+ Resolver.new(description[:symbol]).v(*(description[:args] || []))
60
+ end
61
+
62
+ end
data/lib/rhn/app.rb ADDED
@@ -0,0 +1,31 @@
1
+ require 'sinatra'
2
+ require 'json'
3
+ require 'ruby-hackernews'
4
+
5
+ require 'rhn/util'
6
+ require 'rhn/apigen'
7
+ require 'rhn/controllers'
8
+
9
+ include ApiGen
10
+
11
+
12
+ class RHN < Sinatra::Base
13
+ get '/api/' do
14
+ begin
15
+ decoded = decode_req params[:r]
16
+ result = {:result => from_dsl(decoded)}
17
+ rescue AccessDenied => exc
18
+ status 550
19
+ result = {:error => exc.to_s}
20
+ rescue NotFound => exc
21
+ status 404
22
+ result = {:error => exc.to_s}
23
+ rescue JSON::ParserError
24
+ status 400
25
+ result = {:error => "The parameter you passed couldn't be parsed"}
26
+ end
27
+
28
+ content_type :json
29
+ result.to_json
30
+ end
31
+ end
@@ -0,0 +1,20 @@
1
+ require 'ruby-hackernews'
2
+ require 'rhn/apigen'
3
+
4
+
5
+ class HN
6
+ def hotpage
7
+ RubyHackernews::Entry.all.map {|entry|
8
+ {
9
+ :id => entry.id.to_i,
10
+ :title => entry.link.title,
11
+ :link => entry.link.href,
12
+ :comments_count => entry.comments_count.to_i,
13
+ :voting => entry.voting.score.to_i,
14
+ :user => entry.user.name
15
+ }
16
+ }
17
+ end
18
+ end
19
+
20
+ ApiGen::AccessManager.register HN, "hotpage"
data/lib/rhn/util.rb ADDED
@@ -0,0 +1,12 @@
1
+ require 'cgi'
2
+ require 'json'
3
+
4
+
5
+ def encode_req desc
6
+ CGI::escape(desc.to_json)
7
+ end
8
+
9
+
10
+ def decode_req desc
11
+ JSON.parse(CGI::unescape(desc), :symbolize_names => true)
12
+ end
@@ -0,0 +1,3 @@
1
+ module Rhn
2
+ VERSION = "0.0.3"
3
+ end
data/lib/rhn.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "rhn/version"
2
+
3
+ module Rhn
4
+ # Your code goes here...
5
+ end
data/rhn.gemspec ADDED
@@ -0,0 +1,37 @@
1
+ # -*- mode: ruby; coding: utf-8; -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'rhn/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "rhn"
8
+ spec.version = Rhn::VERSION
9
+ spec.authors = ["Lincoln de Sousa"]
10
+ spec.email = ["lincoln@clarete.li"]
11
+ spec.description = %q{Yet another WEB API for hackernews}
12
+ spec.summary = %q{Yet another WEB API for hackernews. Beware of lazy hack ahead!
13
+ This project is a very thin layer on top of [ruby-hackernews](https://github.com/bolthar/ruby-hackernews) so
14
+ we can access this info through HTTP.
15
+
16
+ The main usage of this API is an [Emacs Client for Hackernews](https://github.com/clarete/hackernews.el).
17
+ }
18
+ spec.homepage = ""
19
+ spec.license = "MIT"
20
+
21
+ spec.files = `git ls-files`.split($/)
22
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
23
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
24
+ spec.require_paths = ["lib"]
25
+
26
+ # Library requirements
27
+ spec.add_dependency "ruby-hackernews"
28
+ spec.add_dependency "sinatra"
29
+ spec.add_dependency "json"
30
+
31
+ # Development requirements
32
+ spec.add_development_dependency "bundler", "~> 1.3"
33
+ spec.add_development_dependency "debugger"
34
+ spec.add_development_dependency "rspec"
35
+ spec.add_development_dependency "rack-test"
36
+ spec.add_development_dependency "bump"
37
+ end
@@ -0,0 +1,82 @@
1
+ require 'rhn/apigen'
2
+
3
+ include ApiGen
4
+
5
+ describe "Access Manager" do
6
+ it "should register objects and provide access for them through a resolver" do
7
+
8
+ # Given that I have a random python object declared somewhere in my
9
+ # computer
10
+ class RandomObject
11
+ def get_stuff_1
12
+ "blah"
13
+ end
14
+
15
+ def get_stuff_2
16
+ "bleh"
17
+ end
18
+ end
19
+
20
+ # When I allow the object and a method to be accessed by my crazy API
21
+ AccessManager.register RandomObject, "get_stuff_1"
22
+
23
+ # Then I see that now the registered method (get_stuff_1) is available but
24
+ # the other one (get_stuff_2) remains protected
25
+ Resolver.new("RandomObject.get_stuff_1").v.should be_eql("blah")
26
+ expect { Resolver.new("RandomObject.get_stuff_2").v }.to raise_error AccessDenied, "You don't have access to this resource"
27
+ end
28
+
29
+ it "should return a smart message when the object does not exist" do
30
+ expect {
31
+ Resolver.new("NoSuchObject.no_such_method").v
32
+ }.to raise_error NotFound, "There's no such object"
33
+ end
34
+
35
+ it "should provide access to attributes" do
36
+ # Given that I have a random object with an attribute
37
+ class RandomObject
38
+ attr_accessor :attr
39
+
40
+ def initialize
41
+ @attr = 'random value'
42
+ end
43
+ end
44
+
45
+ # When I register the attr through the AccessManager
46
+ AccessManager.register RandomObject, 'attr'
47
+
48
+ # Then I see that I can retrieve the right value
49
+ Resolver.new('RandomObject.attr').v.should be_eql('random value')
50
+ end
51
+
52
+ it "should access method that takes parameters" do
53
+ # Given that I have a class with a method that takes parameters
54
+ class RandomObject
55
+ def sum a, b
56
+ a + b
57
+ end
58
+ end
59
+
60
+ # When I register the attr in the AccessManager
61
+ AccessManager.register RandomObject, 'sum'
62
+
63
+ # Then I see that it's possible to pass arguments to my function
64
+ Resolver.new('RandomObject.sum').v(2, 2).should be_eql(4)
65
+ end
66
+
67
+ it "should provide an easier way to resolve symbols" do
68
+ # Given that I have a class with a method that takes parameters and
69
+ # properly registered in the access manager
70
+ class RandomObject
71
+ def sum a, b
72
+ a + b
73
+ end
74
+ end
75
+
76
+ AccessManager.register RandomObject, 'sum'
77
+
78
+ # When I query for the symbol using a dsl-ish description contained in a
79
+ # dictionary, I see that I still get my results! :)
80
+ ApiGen::from_dsl({:symbol => 'RandomObject.sum', :args => [2, 2]}).should be_eql(4)
81
+ end
82
+ end
data/spec/api_spec.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'ruby-hackernews'
2
+ require 'spec_helper'
3
+
4
+ require 'rhn/util'
5
+
6
+
7
+ describe "Hackernews", "#hotpage" do
8
+ it "It should return the list of posts on the hot page" do
9
+ # Given that we mock some posts
10
+ RubyHackernews::Entry.should_receive(:all).and_return [
11
+ mock_entry("1", "My post", "http://blog.c.o/p/1", 223, 12345, "clarete"),
12
+ mock_entry("2", "Another post", "http://blog.c.o/p/22", 239, 3433, "guerrinha")]
13
+
14
+ # When we request the hotpage posts
15
+ desc = encode_req({:symbol => 'HN.hotpage'})
16
+ get "/api/?r=#{desc}"
17
+
18
+ # Then I see that I got all the entries available
19
+ JSON.parse(last_response.body, :symbolize_names => true).should be_eql(
20
+ {:result => [
21
+ {:id => 1,
22
+ :title => "My post",
23
+ :link => "http://blog.c.o/p/1",
24
+ :comments_count => 223,
25
+ :voting => 12345,
26
+ :user => "clarete"},
27
+ {:id => 2,
28
+ :title => "Another post",
29
+ :link => "http://blog.c.o/p/22",
30
+ :comments_count => 239,
31
+ :voting => 3433,
32
+ :user => "guerrinha"}
33
+ ]}
34
+ )
35
+ end
36
+ end
@@ -0,0 +1,104 @@
1
+ require 'cgi'
2
+ require 'json'
3
+ require 'spec_helper'
4
+
5
+ require 'rhn/util'
6
+ require 'rhn/apigen'
7
+
8
+ describe "Web Access" do
9
+
10
+ it "should be possible to encode requested symbols" do
11
+ # Given that I have a request to the API described in the mini-dsl lang
12
+ req = {"symbol" => 'MyObject', "args" => [1, 2]}
13
+
14
+ # When I prepare the request
15
+ prepared = encode_req(req)
16
+
17
+ # Then I see that it was transformed into a json string encoded by the
18
+ # ruby's `CGI::escape` function.
19
+ JSON.parse(CGI::unescape(prepared)).should be_eql(req)
20
+ end
21
+
22
+ it "should be possible to decode requested symbols" do
23
+ # Given that I have an encoded param
24
+ encoded_req = \
25
+ '%7B%22symbol%22%3A+%22MyObject%22%2C+%22args%22%3A+%5B1%2C+2%5D%7D'
26
+
27
+ # When I decode the param above
28
+ decoded = decode_req(encoded_req)
29
+
30
+ # Then I see that it was transformed in a dict
31
+ decoded.should be_eql({:symbol => 'MyObject', :args => [1, 2]})
32
+ end
33
+
34
+ it "should provide access for classes registered in the access manager" do
35
+
36
+ # Given that I have an object registered in the AccessManager
37
+ class Stuff
38
+ def mul a, b
39
+ a * b
40
+ end
41
+ end
42
+
43
+ ApiGen::AccessManager.register Stuff, 'mul'
44
+
45
+ # When I hit the API that resolves objects with the right parameters
46
+ desc = encode_req({:symbol => 'Stuff.mul', :args => [2, 2]})
47
+ get "/api/?r=#{desc}"
48
+
49
+ # Then I see that the result was right
50
+ last_response.status.should be_eql 200
51
+ last_response.headers["content-type"].should be_eql "application/json;charset=utf-8"
52
+ JSON.parse(last_response.body).should be_eql({'result' => 4})
53
+ end
54
+
55
+ it "should return an error code when the user tries to access denied resources" do
56
+ # Given that I have an object registered in the AccessManager with
57
+ # unregistered symbols
58
+ class Calc
59
+ def sum a, b
60
+ a + b
61
+ end
62
+ def mul a, b
63
+ a * b
64
+ end
65
+ end
66
+
67
+ ApiGen::AccessManager.register Calc, 'mul'
68
+
69
+ # When I try to access the unregistered symbol
70
+ desc = encode_req({:symbol => 'Stuff.sum', :args => [2, 2]})
71
+ get "/api/?r=#{desc}"
72
+
73
+ # Then I receive an error message saying that I have no permission to
74
+ # access that
75
+ last_response.status.should be_eql 550
76
+ last_response.headers["content-type"].should be_eql "application/json;charset=utf-8"
77
+ JSON.parse(last_response.body).should be_eql({'error' => "You don't have access to this resource"})
78
+ end
79
+
80
+ it "should return the proper status and message when the resource is not found" do
81
+ # When I try to access the unregistered object
82
+ desc = encode_req({:symbol => 'NoSuchObj.no_such_method', :args => [2, 2]})
83
+ get "/api/?r=#{desc}"
84
+
85
+ # Then I should see the proper error message raised with a nice message
86
+ last_response.status.should be_eql 404
87
+ last_response.headers["content-type"].should be_eql "application/json;charset=utf-8"
88
+ JSON.parse(last_response.body).should be_eql({'error' => "There's no such object"})
89
+ end
90
+
91
+ it "should handle invalid requests with the right status and nice message" do
92
+ # Given that I have a buggy query parameter
93
+ query = 'invalid'
94
+
95
+ # When I hit the API end point with that invalid param
96
+ get "/api/?r=#{query}"
97
+
98
+ # Then I see that a proper error message was set
99
+ last_response.status.should be_eql 400
100
+ last_response.headers["content-type"].should be_eql "application/json;charset=utf-8"
101
+ JSON.parse(last_response.body).should be_eql(
102
+ {'error' => "The parameter you passed couldn't be parsed"})
103
+ end
104
+ end
@@ -0,0 +1,29 @@
1
+ require 'rack/test'
2
+ require 'sinatra'
3
+ require 'ruby-hackernews'
4
+
5
+ require 'rhn/app'
6
+
7
+ # setup test environment
8
+ set :environment, :test
9
+ set :run, false
10
+ set :raise_errors, true
11
+ set :logging, false
12
+
13
+ def app
14
+ RHN
15
+ end
16
+
17
+ RSpec.configure do |config|
18
+ config.include Rack::Test::Methods
19
+ end
20
+
21
+ def mock_entry id, title, link, ccount, voting, user
22
+ link = mock(Object, :title => title, :href => link)
23
+ mock(RubyHackernews::Entry,
24
+ :id => id,
25
+ :link => link,
26
+ :comments_count => ccount,
27
+ :voting => mock(Object, :score => voting),
28
+ :user => mock(Object, :name => user))
29
+ end
metadata ADDED
@@ -0,0 +1,184 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rhn
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Lincoln de Sousa
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-10-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: ruby-hackernews
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sinatra
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: json
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ! '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '1.3'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '1.3'
69
+ - !ruby/object:Gem::Dependency
70
+ name: debugger
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: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rack-test
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: bump
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ! '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description: Yet another WEB API for hackernews
126
+ email:
127
+ - lincoln@clarete.li
128
+ executables:
129
+ - rhn
130
+ extensions: []
131
+ extra_rdoc_files: []
132
+ files:
133
+ - .gitignore
134
+ - Gemfile
135
+ - Gemfile.lock
136
+ - LICENSE.txt
137
+ - Makefile
138
+ - README.md
139
+ - Rakefile
140
+ - bin/rhn
141
+ - config.ru
142
+ - lib/rhn.rb
143
+ - lib/rhn/apigen.rb
144
+ - lib/rhn/app.rb
145
+ - lib/rhn/controllers.rb
146
+ - lib/rhn/util.rb
147
+ - lib/rhn/version.rb
148
+ - rhn.gemspec
149
+ - spec/api_gen_spec.rb
150
+ - spec/api_spec.rb
151
+ - spec/api_web_acces_spec.rb
152
+ - spec/spec_helper.rb
153
+ homepage: ''
154
+ licenses:
155
+ - MIT
156
+ metadata: {}
157
+ post_install_message:
158
+ rdoc_options: []
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ! '>='
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ! '>='
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ requirements: []
172
+ rubyforge_project:
173
+ rubygems_version: 2.1.9
174
+ signing_key:
175
+ specification_version: 4
176
+ summary: Yet another WEB API for hackernews. Beware of lazy hack ahead! This project
177
+ is a very thin layer on top of [ruby-hackernews](https://github.com/bolthar/ruby-hackernews)
178
+ so we can access this info through HTTP. The main usage of this API is an [Emacs
179
+ Client for Hackernews](https://github.com/clarete/hackernews.el).
180
+ test_files:
181
+ - spec/api_gen_spec.rb
182
+ - spec/api_spec.rb
183
+ - spec/api_web_acces_spec.rb
184
+ - spec/spec_helper.rb