hacker-news-client (Ruby)
Zero-dependency Ruby gem for the Hacker News Firebase API. Pure stdlib (Net::HTTP + Thread + Queue). Class-per-variant item modeling with polymorphic from_hash factory. Part of the cross-language hacker-news-client suite.
Install
gem install hacker-news-client
Or add to your Gemfile:
gem 'hacker-news-client', '~> 0.1.0'
Usage
require 'hacker/news/client'
client = Hacker::News::Client.new
# Single item
item = client.item(1)
puts item.title if item.is_a?(Hacker::News::Story)
# Case on variant (Ruby 3.0+ pattern matching)
case item
in Hacker::News::Story(title:, score:) then puts "#{title} (#{score})"
in Hacker::News::Comment(text:, parent:) then puts "comment on #{parent}"
in nil then puts 'deleted or missing'
end
# Batch
items = client.items([1, 15, 100])
# Top stories, hydrated
top = client.top_stories(limit: 10)
# Recursive comment tree
tree = client.comment_tree(8863)
# User profile
user = client.user('pg')
Configuration
Hacker::News::Client.new(
base_url: 'https://hacker-news.firebaseio.com/v0', # default
timeout: 10.0, # seconds
concurrency: 10, # batch fan-out cap
user_agent: 'my-app/1.0',
transport: ->(url, timeout, ua) { ... } # optional, for tests
)
The transport: lambda is the injection point for mocking — see test/test_unit.rb for the pattern.
Error handling
begin
client.item(1)
rescue Hacker::News::HttpError => err
warn "HTTP #{err.status} at #{err.url}"
rescue Hacker::News::TimeoutError
warn 'timed out'
rescue Hacker::News::TransportError => err
warn "network: #{err.}"
rescue Hacker::News::JsonError
warn 'invalid JSON'
rescue Hacker::News::Error => err
warn err.
end
nil from item / user means the API returned null — not an error. Deleted stubs also surface as nil.
Item variants
Hacker::News::Item # abstract base
├─ Hacker::News::Story # title, score, descendants, url, text, kids
├─ Hacker::News::Comment # parent, text, kids
├─ Hacker::News::Job # title, score, url, text
├─ Hacker::News::Poll # title, score, descendants, parts, text, kids
└─ Hacker::News::PollOpt # poll, score, text
Hacker::News::Item.from_hash(h) builds the matching subclass from a decoded payload.
Full API
See the cross-language contract (DESIGN.md). Methods are snake_case:
| Method | Returns |
|---|---|
item(id) |
Item or nil |
items(ids) |
Array<Item> — order-preserving, nils dropped |
user(username) |
User (Struct) or nil |
max_item |
Integer |
updates |
Updates (Struct) |
top_story_ids / new_story_ids / best_story_ids / ask_story_ids / show_story_ids / job_story_ids |
Array<Integer> |
top_stories(limit: 30) / ... |
hydrated Array<Item> |
comment_tree(id) |
CommentTreeNode (Struct) or nil |
Tests
cd ruby
bundle install
rake test # 41 tests: 16 integration + 25 unit
rubocop # lint
Coverage: 100% line / 96.96% branch via SimpleCov.
Example
ruby example.rb
Links
License
MIT © hacker-news-client contributors. See LICENSE.