Skip to content

Instantly share code, notes, and snippets.

@jtanium
Created November 29, 2010 20:55
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jtanium/720605 to your computer and use it in GitHub Desktop.
Save jtanium/720605 to your computer and use it in GitHub Desktop.
Service Oriented Design with Ruby and Rails (examples that actually work)
require 'rubygems'
require 'active_record'
require 'sinatra'
require 'models/user'
require 'logger'
env_index = ARGV.index("-e")
env_arg = ARGV[env_index+1] if env_index
env = env_arg || ENV["SINATRA_ENV"] || "development"
databases = YAML.load_file("config/database.yml")
SINATRA_LOGGER = Logger.new(File.open("log/#{env}.log", "w+"))
ActiveRecord::Base.logger = SINATRA_LOGGER
ActiveRecord::Base.establish_connection(databases[env])
ActiveRecord::Base.include_root_in_json = false # don't include "user: {...}"
# HTTP entry points
# get a user by name
get '/api/v1/users/:name' do
user = User.find_by_name(params[:name])
if user
user.to_json
else
error 404, {:error => "user not found"}.to_json
end
end
post '/api/v1/users' do
begin
user = User.create(JSON.parse(request.body.read))
if user.valid?
user.to_json
else
error 400, user.errors.to_json
end
rescue => e
error 400, e.message.to_json
end
end
require 'rubygems'
require 'active_record'
require 'sinatra'
require 'models/user'
require 'logger'
env_index = ARGV.index("-e")
env_arg = ARGV[env_index+1] if env_index
env = env_arg || ENV["SINATRA_ENV"] || "development"
databases = YAML.load_file("config/database.yml")
SINATRA_LOGGER = Logger.new(File.open("log/#{env}.log", "w+"))
ActiveRecord::Base.logger = SINATRA_LOGGER
ActiveRecord::Base.establish_connection(databases[env])
ActiveRecord::Base.include_root_in_json = false # don't include "user: {...}"
# HTTP entry points
# get a user by name
get '/api/v1/users/:name' do
user = User.find_by_name(params[:name])
if user
user.to_json
else
error 404, {:error => "user not found"}.to_json
end
end
# create a new user
post '/api/v1/users' do
begin
user = User.create(JSON.parse(request.body.read))
if user.valid?
user.to_json
else
error 400, user.errors.to_json
end
rescue => e
error 400, e.message.to_json
end
end
# update an existing user
put '/api/v1/users/:name' do
user = User.find_by_name(params[:name])
if user
begin
if user.update_attributes(JSON.parse(request.body.read))
user.to_json
else
error 400, user.errors.to_json
end
rescue => e
error 400, e.message.to_json
end
else
error 404, {:error => "user not found"}.to_json
end
end
# destroy an existing user
delete '/api/v1/users/:name' do
user = User.find_by_name(params[:name])
if user
user.destroy
user.to_json
else
error 404, {:error => "user not found"}.to_json
end
end
require File.dirname(__FILE__) + "/../service"
require 'rspec' # 'spec' is now 'rspec'; JE
# require 'spec/interop/test' # I have no idea what this was, but it won't work now; JE
require 'rack/test'
set :environment, :test
# Test::Unit::TestCase.send :include, Rack::Test::Methods # this is old; JE
# Do this instead of TestCase.send :include, ...; JE
RSpec.configure do |conf|
conf.include Rack::Test::Methods
end
def app
Sinatra::Application
end
describe "service" do
before(:each) do
User.create(
:name => "paul",
:email => "paul@pauldix.net",
:password => "strongpass",
:bio => "rubyist")
end
# the User.create will only work the first time, so empty out the database after
# each test; JE
after(:each) do
User.delete_all
end
it "should return a user by name" do
get '/api/v1/users/paul'
last_response.should be_ok
attributes = JSON.parse(last_response.body)
attributes["name"].should == "paul"
end
it "should return a user with an email" do
get '/api/v1/users/paul'
last_response.should be_ok
attributes = JSON.parse(last_response.body)
attributes["email"].should == "paul@pauldix.net"
end
it "should not return a user's password" do
get '/api/v1/users/paul'
last_response.should be_ok
attributes = JSON.parse(last_response.body)
attributes.should_not have_key("password")
end
it "should return a user with a bio" do
get '/api/v1/users/paul'
last_response.should be_ok
attributes = JSON.parse(last_response.body)
attributes["bio"].should == "rubyist"
end
it "should return a 404 for users that don't exist" do
get '/api/v1/users/foo'
last_response.status.should == 404
end
end
describe "POST on /api/v1/users" do
it "should create a user" do
User.transaction do # wrap this in a transaction so other users can be created; JE
num_users = User.count
post '/api/v1/users', {
:name => "trotter",
:email => "no spam",
:password => "whatever",
:bio => "southern belle"}.to_json
last_response.should be_ok
User.count.should == num_users+1
# Don't do another test on GET, we spec'd that above; JE
raise ActiveRecord::Rollback # rollback the transaction; JE
end
end
end
describe "PUT on /api/v1/users/:name" do # we're using :name, not :id; JE
it "should update a user" do
User.transaction do # wrap this in a transaction so other users can be created; JE
u = User.create(
:name => "bryan",
:email => "no spam",
:password => "whatever",
:bio => "rspec master")
put '/api/v1/users/bryan', {:bio => "testing freak"}.to_json
last_response.should be_ok
get '/api/v1/users/bryan'
attributes = JSON.parse(last_response.body)
attributes["bio"].should == "testing freak"
raise ActiveRecord::Rollback # rollback the transaction; JE
end
end
end
describe "DELETE on /api/v1/users/:id" do
it "should delete a user" do
User.transaction do # wrap this in a transaction so other users can be created; JE
User.create(
:name => "francis",
:email => "no spam",
:password => "whatever",
:bio => "williamsburg hipster")
delete '/api/v1/users/francis'
last_response.should be_ok
get '/api/v1/users/francis'
last_response.status.should == 404
raise ActiveRecord::Rollback # rollback the transaction; JE
end
end
end
@dtuite
Copy link

dtuite commented Jan 15, 2012

This helped me out a lot. Thanks

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment