iwantcoding.com
🔥 Daily 👥 Rooms 🏆 Top Log in Sign up

Examples

Five practical Ruby snippets: JSON over HTTP, CSV parsing, a small DSL, fibers for streaming, and a Rails service object.

Five Ruby recipes

EXAMPLE
# 1) JSON over HTTP with Net::HTTP
require 'net/http'
require 'json'
require 'uri'

def fetch_json(url, headers: {})
  uri = URI(url)
  req = Net::HTTP::Get.new(uri)
  headers.each { |k, v| req[k] = v }
  res = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https',
                        open_timeout: 5, read_timeout: 10) { |http| http.request(req) }
  raise "HTTP \#{res.code}" unless res.code.start_with?('2')
  JSON.parse(res.body)
end

orders = fetch_json('https://api.example.com/orders',
                     headers: { 'Authorization' => 'Bearer XYZ' })

# 2) CSV parsing with headers + types
require 'csv'

CSV.foreach('orders.csv', headers: true, header_converters: :symbol) do |row|
  total = row[:total_cents].to_i / 100.0
  puts "\#{row[:customer]} : $\#{format('%.2f', total)}"
end

# Write CSV
CSV.open('out.csv', 'w', headers: true, write_headers: true) do |csv|
  csv << %w[id name email]
  csv << %w[1 Alice alice@example.com]
end

# 3) Tiny internal DSL — method_missing + block_given?
class Pipeline
  def self.build(&block)
    p = new
    p.instance_eval(&block)
    p
  end

  def step(name)
    @steps ||= []
    @steps << name
  end

  def run(input)
    @steps.reduce(input) { |val, step| send(step, val) }
  end

  private

  def clean(s); s.strip end
  def upcase(s); s.upcase end
  def reverse(s); s.reverse end
end

p = Pipeline.build do
  step :clean
  step :upcase
  step :reverse
end
puts p.run('  hello  ')      # 'OLLEH'

# 4) Streaming with Enumerator::Lazy
# Process a giant log file without loading it all
File.foreach('app.log').lazy
    .map(&:strip)
    .reject(&:empty?)
    .select { |l| l.include?('ERROR') }
    .first(100)
    .each { |l| puts l }

# 5) Rails service object
# app/services/place_order.rb
class PlaceOrder
  def initialize(customer:, items:)
    @customer = customer
    @items = items
  end

  def call
    Order.transaction do
      order = @customer.orders.create!(total_cents: total_cents)
      @items.each { |i| order.line_items.create!(i) }
      OrderMailer.with(order: order).placed.deliver_later
      order
    end
  end

  private

  def total_cents
    @items.sum { |i| i[:price_cents] * i[:qty] }
  end
end

# Use it
# PlaceOrder.new(customer: current_user, items: items).call

# ===== Patterns to internalise =====
# - Net::HTTP is fine for one-off scripts; use Faraday / HTTPX for production
# - CSV with headers + symbol header_converters keeps code readable
# - Internal DSLs are a Ruby superpower; keep them small
# - Lazy enumerators stream giant inputs without memory blow-up
# - Service objects make controllers thin and tests fast

# ===== Pitfalls =====
# - Net::HTTP without read_timeout -> hangs forever on slow servers
# - CSV.read on a giant file -> OOM. Use CSV.foreach
# - Catching Exception (not StandardError) -> swallows SystemExit + Interrupt
# - Mutating method arguments in block-yielded methods -> surprising callers

Why it matters

Reach for service objects in Rails as soon as a controller action grows past 10 lines. The class becomes the seam where business rules + transactions + mailers live together, controllers stay focused on the HTTP layer, and tests run as plain Ruby with no controller setup overhead.

Tip: Tweak the snippet with Try it Yourself », then sit the quiz at the bottom of the page.

Example

Example
# Pure Ruby + Sinatra is a great gateway. Rails ships everything you need.
Try it Yourself »

Discussion

Loading…