Created
December 1, 2011 16:12
-
-
Save lucatironi/1417872 to your computer and use it in GitHub Desktop.
Snippets for an API with grape
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Server App | |
# This file must be in lib/myapp/api.rb | |
module MyApp | |
module Entities | |
class Products < Grape::Entity | |
expose :id, :code, :name, :short_description | |
expose :description, :unless => { :collection => true } | |
expose (:category) { |model, options| model.category.name } | |
expose (:brand) { |model, options| model.brand.name } | |
end | |
class Category < Grape::Entity | |
expose :id, :name | |
end | |
class Brand < Grape::Entity | |
expose :id, :name | |
end | |
class Costumer < Grape::Entity | |
expose :id, :first_name, :last_name, :email | |
end | |
end | |
class API < Grape::API | |
prefix "api" | |
version "v1", :using => :path, :vendor => "foo", :format => :json | |
http_basic do |user, pass| | |
user == "apiuser" && pass == "secret" | |
end | |
# Products | |
resource :products do | |
get do | |
present Product.all, :with => Entities::Product | |
end | |
get ':id' do | |
present Product.find(params[:id]), :with => Entities::Product | |
end | |
end | |
# Category | |
resource :categories do | |
get do | |
present Category.all, :with => Entities::Category | |
end | |
get ':id' do | |
present Category.find(params[:id]), :with => Entities::Category | |
end | |
get ':id/products' do | |
present Product.where(:category_id => params[:id]).all, :with => Entities::Product | |
end | |
end | |
# Brands | |
resource :brands do | |
get do | |
present Brand.all, :with => Entities::Brand | |
end | |
get ':id' do | |
present Brand.find(params[:id]), :with => Entities::Brand | |
end | |
get ':id/products' do | |
present Product.where(:brand_id => params[:id]).all, :with => Entities::Product | |
end | |
end | |
# Customers | |
resource :customer do | |
post do | |
customer = Customer.find_by_email(params[:customer][:email]) | |
if customer.nil? | |
customer = Customer.create(params[:customer]) | |
end | |
present customer, :with => Entities::Customer | |
end | |
get ':id' do | |
present Customer.find(params[:id]), :with => Entities::Customer | |
end | |
end | |
# Subscribers | |
resource :subscribers do | |
post do | |
if subscriber = Subscriber.create(params[:subscriber]) | |
present subscriber | |
else | |
error! "Unable to create your subscriber", 403 | |
end | |
end | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# References | |
Grape: An opinionated micro-framework for creating REST-like APIs in Ruby. https://github.com/intridea/grape | |
Mounting Grape API inside rails application: http://martinciu.com/2011/01/mounting-grape-api-inside-rails-application.html | |
RailsCast on ActiveModel: http://railscasts.com/episodes/219-active-model |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Client App: the product is not an active_record | |
# Require httparty in Gemfile | |
class Product | |
attr_accessor :id, :code, :name, :category, :brand, :short_description, :description | |
def initialize(product_id = nil) | |
return nil if product_id.nil? | |
response = HTTParty.get(APP_CONFIG[:api_domain] + "/api/v1/products/#{product_id}", :basic_auth => { :username => "apiuser", :password => "secret" }) | |
response.parsed_response.each do |name, value| | |
send("#{name}=", value) | |
end | |
end | |
def persisted? | |
false | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
MyApp::Application.routes.draw do | |
# snip.. | |
mount Pvgest::API => "/" #API will be available under "/api/v1" url because of setting from MyApp::API line 4 | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# This file is copied to spec/ when you run 'rails generate rspec:install' | |
ENV["RAILS_ENV"] ||= 'test' | |
require File.expand_path("../../config/environment", __FILE__) | |
require 'rspec/rails' | |
require 'webmock/rspec' | |
# Requires supporting ruby files with custom matchers and macros, etc, | |
# in spec/support/ and its subdirectories. | |
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f} | |
RSpec.configure do |config| | |
# == Mock Framework | |
# | |
# If you prefer to use mocha, flexmock or RR, uncomment the appropriate line: | |
# | |
# config.mock_with :mocha | |
# config.mock_with :flexmock | |
# config.mock_with :rr | |
config.mock_with :rspec | |
# Remove this line if you're not using ActiveRecord or ActiveRecord fixtures | |
config.fixture_path = "#{::Rails.root}/spec/fixtures" | |
# If you're not using ActiveRecord, or you'd prefer not to run each of your | |
# examples within a transaction, remove the following line or assign false | |
# instead of true. | |
config.use_transactional_fixtures = true | |
config.before(:each) do | |
WebMock.reset! | |
categories = JSON.parse(File.open('spec/fixtures/categories.json', 'r').read) | |
produttori = JSON.parse(File.open('spec/fixtures/brands.json', 'r').read) | |
products = JSON.parse(File.open('spec/fixtures/products.json', 'r').read) | |
stub_request(:get, "http://apiuser:[email protected]/api/v1/categories").to_return(:status => 200, :headers => {}, :body => categories) | |
stub_request(:get, "http://apiuser:[email protected]/api/v1/brands").to_return(:status => 200, :headers => {}, :body => brands) | |
stub_request(:get, "http://apiuser:[email protected]/api/v1/products").to_return(:status => 200, :headers => {}, :body => products) | |
stub_request(:post, "http://apiuser:[email protected]/api/v1/customers").to_return(:status => 200, :headers => {}, :body => {:id => 1, :nome => "John", :cognome => "Doe"}) | |
stub_request(:get, "http://apiuser:[email protected]/api/v1/customers/1").to_return(:status => 200, :headers => {}, :body => {:nome => "John", :cognome => "Doe"}) | |
stub_request(:post, "http://apiuser:[email protected]/api/v1/customers").to_return(:status => 200, :headers => {}, :body => {:id => 1, :email => "[email protected]", :referer => "http://www.google.com", :ip => "10.10.10.100" }) | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Client App: subscribers are sent to the api | |
class SubscribersController < ApplicationController | |
def create | |
options = { :body => { :subscriber => { :email => params[:email], :ip => request.env['REMOTE_ADDR'], :referer => request.env['HTTP_REFERER'] } }, :basic_auth => { :username => "apiuser", :password => "secret" } } | |
response = HTTParty.post(APP_CONFIG[:api_domain] + "/api/v1/subscribers", options) | |
if response.status == 200 | |
redirect_to root_url, :notice => "Thanks!" | |
else | |
redirect_to root_url, :notice => "Error..." | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Client App: user model | |
class User < ActiveRecord::Base | |
has_secure_password | |
attr_accessible :email, :first_name, :last_name, :phone, :password, :password_confirmation | |
validates_presence_of :name, :fisrt_name, :email | |
validates_uniqueness_of :email | |
validates_format_of :email, :with => /^[-a-z0-9_+\.]+\@([-a-z0-9]+\.)+[a-z0-9]{2,4}$/i | |
validates :phone, | |
:length => { :minimum => 6, :maximum => 15 }, | |
:format => { :with => /^[+\/\-() 0-9]{6,15}$/ }, | |
:allow_blank => true | |
before_validation :generate_random_password, :on => :create | |
before_create :set_customer | |
def self.default | |
new | |
end | |
def generate_random_password | |
self.password = Array.new(10).map { (65 + rand(58)).chr }.join | |
end | |
def set_customer | |
options = { :body => { :customer => { :email => self.email, :firt_name => self.first_name, :last_name => self.last_name, :phone => self.phone } }, :basic_auth => { :username => "apiuser", :password => "secret" } } | |
response = HTTParty.post(APP_CONFIG[:api_domain] + "/api/v1/customers", options) | |
self.cliente_id = response.parsed_response['id'] | |
end | |
def customer | |
response = HTTParty.get(APP_CONFIG[:api_domain] + "/api/v1/customers/#{customer_id}", :basic_auth => { :username => "apiuser", :password => "secret" }) | |
return response.parsed_response | |
end | |
def send_password_reset | |
generate_token(:password_reset_token) | |
self.password_reset_sent_at = Time.zone.now | |
save! | |
PostOffice.password_reset(self).deliver | |
end | |
private | |
def generate_token(column) | |
begin | |
self[column] = SecureRandom.urlsafe_base64 | |
end while User.exists?(column => self[column]) | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment