
E ai programador(a), você sabe como criar uma API Ruby on Rails rapidamente?
API’s são maneiras de conectar serviços, com elas é possível se conectar ao Google para traduzir uma frase ou ao Watson da IBM para realizar um processamento de linguagem natural.
Saber como criar e consumir API’s é fundamental para qualquer programador, então nessa pequena série com 3 vídeos nós vamos ver o que é essencial para criar uma usando Ruby On Rails.
O que vamos utilizar
- Ruby
- Ruby On Rails
- Devise
- Devise Simple Token
- Rack Cors
- Rack Attack
- Postman
Planejando nossa API
Preparando a base da API
Gerando nosso Projeto
1 – Rode no console
1 |
rails new OneBitContacts --api |
*Se quiser utilizar o PostgreSQL adicione ao comando:
1 |
--database=postgresql |
Versionando a API
1 – Dentro da pasta controllers crie uma pasta chamada api
2 – Dentro da pasta criada crie uma nova pasta chamada v1
3 – Dentro da pasta criada crie um arquivo chamado api_controller.rb e coloque nele:
1 2 3 4 5 6 7 8 9 |
module Api::V1 class ApiController < ApplicationController # Métodos globais end end |
Habilitando o CORS
Acrescente no seu Gemfile:
1 |
gem 'rack-cors' |
Instale a gem rodando:
1 |
bundle install |
Acrescente no seu config/application.rb:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
config.middleware.insert_before 0, Rack::Cors do allow do origins '*' resource '*', headers: :any, methods: %i(get post put patch delete options head) end end |
Configurando o Rack Attack
Acrescente no seu Gemfile:
1 |
gem 'rack-attack' |
Instale a Gem:
1 |
bundle |
Acrescente em config/application:
1 |
config.middleware.use Rack::Attack |
Crie um arquivo chamado rack_attack.rb no seu config/initializers/ e coloque nele:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
class Rack::Attack Rack::Attack.cache.store = ActiveSupport::Cache::MemoryStore.new # Allow all local traffic safelist('allow-localhost') do |req| '127.0.0.1' == req.ip || '::1' == req.ip end # Allow an IP address to make 10 requests every 10 seconds throttle('req/ip', limit: 5, period: 5) do |req| req.ip end # Throttle login attempts by email address #throttle("logins/email", limit: 5, period: 20.seconds) do |req| # if req.path == '/users/sign_in' && req.post? # req.params['email'].presence # end #end end |
Instalando o Devise
Acrescente no seu Gemfile:
1 |
gem 'devise' |
Instale rodando:
1 |
bundle install |
Em config/environments/development.rb coloque:
1 |
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 } |
Rode no console:
1 |
rails generate devise:install |
Rode no console:
1 2 3 |
rails generate devise User rails g migration addNameToUser name:string |
Gere as migrations:
1 |
rails db:migrate |
Devise Simple Token
Adicione ao seu Gemfile:
1 |
gem 'simple_token_authentication', '~> 1.0' |
Instale rodando:
1 |
bundle install |
Adicione ao seu User Model:
1 |
acts_as_token_authenticatable |
Rode no console:
1 2 3 |
rails g migration add_authentication_token_to_users "authentication_token:string{30}:uniq" rake db:migrate |
Coloque no seu controler api/v1/api_controller.rb:
1 2 3 4 5 6 7 8 9 10 11 |
acts_as_token_authentication_handler_for User before_action :require_authentication! private def require_authentication! throw(:warden, scope: :user) unless current_user.presence end |

Desenvolvendo e testando nossa API
Gerando nossos Models
Rode no console:
1 2 3 |
rails g model Contact name:string email:string phone:string description:text user:references rails db:migrate |
Adicione ao seu Model Contact:
1 |
validates :name, :user, presence: true |
Adicione ao seu Model User:
1 |
has_many :contacts, dependent: :destroy |
Gerando nossos Controllers
Rode no console:
1 |
rails g controller api/v1/contacts |
Coloque no controller gerado:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 |
class Api::V1::ContactsController < Api::V1::ApiController before_action :set_contact, only: [:show, :update, :destroy] before_action :require_authorization!, only: [:show, :update, :destroy] # GET /api/v1/contacts def index @contacts = current_user.contacts render json: @contacts end # GET /api/v1/contacts/1 def show render json: @contact end # POST /api/v1/contacts def create @contact = Contact.new(contact_params.merge(user: current_user)) if @contact.save render json: @contact, status: :created else render json: @contact.errors, status: :unprocessable_entity end end # PATCH/PUT /api/v1/contacts/1 def update if @contact.update(contact_params) render json: @contact else render json: @contact.errors, status: :unprocessable_entity end end # DELETE /api/v1/contacts/1 def destroy @contact.destroy end private # Use callbacks to share common setup or constraints between actions. def set_contact @contact = Contact.find(params[:id]) end # Only allow a trusted parameter "white list" through. def contact_params params.require(:contact).permit(:name, :email, :phone, :description) end def require_authorization! unless current_user == @contact.user render json: {}, status: :forbidden end end end |
Ajustando as Rotas
Atualize o seu arquivo routes.rb colocando:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Rails.application.routes.draw do devise_for :users namespace :api do namespace :v1 do resources :contacts end end # constraints subdomain: 'api' do # scope module: 'api' do # namespace :v1 do # resources :contacts # end # end # end end |
Testando nossos endpoints
Teste usando Postman ou CURL como no vídeo
Desafios
1 – Paginar os retornos do endpoint /contacts
2 – Criar a estrutura para permitir a inclusão de multiplos endereços nos Contatos
Link para o Gihtub: https://github.com/leonardoscorza/api-completa-rails
Gostou de aprender a criar uma API Ruby On Rails do zero? Comenta aí em baixo para eu saber. 🙂
Obrigado pela sua presença,
Grande abraço!
Leonardo Scorza

Não perca nenhum conteúdo
Receba nosso resumo semanal com os novos posts, cursos, talks e vagas o/
Primeira vez no OneBitCode? Curtiu esse conteúdo?
O OneBitCode tem muito mais para você!
O OneBitCode traz conteúdos de qualidade, e em português, sobre programação com foco em Ruby on Rails e também JavaScript.
Além disso, aqui sempre levamos à você conteúdos valiosos sobre a carreira de programação, dicas sobre currículos, portfólios, perfil profissional, soft skills, enfim, tudo o que você precisa saber para continuar evoluindo como Programador(a)!
Fique por dentro de todos os conteúdos o/
Nossas redes sociais:
📹 • https://youtube.com/Onebitcode [Live todas as terças-feiras às 19h)
💻 • https://linkedin.com/company/onebitcode
🙂 • https://facebook.com/onebitcode
📱 • https://instagram.com/one_bit_code
🐦 • https://twitter.com/onebitcode
Nossos cursos:
🥇 • Programador Full Stack Javascript em 8 Semanas
💎 • Curso Completo de Ruby
⚙ • Minicurso: API Rails 5 Completo
🐞 • Minicurso de Testes para Ruby on Rails com RSpec
Espero que curta nossos conteúdos e sempre que precisar de ajuda, fala com a gente!
Estamos aqui para você 🙂
Bem-vindo à família OneBitCode o/

Boa tarde, Artigo excelente, vi que no final do video 2, voce faz um teste criando um usuario pelo rails c, mas quando faço o mesmo teste ele parece não estar ligado a base de dados, que no meu caso deixei o padrão sqlLite, porem eu dou um create e ele me retorna o que enviei como parametro e os outros campos do User com nil, mas não grava e nem gera o created_at e nem o autenticate. Uma coisa que notei é que quando voce da o rails c, aparece um numero como prefixo, e o meu esta aparecendo… Read more »
Achei o problema, era o banco de dados do sqlite que estava errado no database.yml. Tudo certo
Abraço.

Cara estava a seguir o tutorial e ao fazer o teste esta a me retornar isso
“status”: 404,
“error”: “Not Found”,
“exception”: “#”,
o get que estou a testar com ele é “http://localhost:3000/api/v1/contacts.json”

Bom dia Leonardo Scorza, no seu ultimo exemplo das “Routes” você esqueceu de colocar o devise, eu olhei o seu código no github, e la na sua “Routes” tinha o “devise_for :users” e no tutorial aqui você não colocou, acho que a galera deve ter ficado meio perdida com os erros. Gostei do seu tutorial apesas de sofrer um pouco kkk. vlw abraços!!

De nada mano, gosto dos seus tutoriais!!
Bacana dms, ótimo artigo. Só estou tendo um problema tentei fazer usando um nome de model diferente de contact, e não estou conseguindo.
Muito bem explicado, parabéns,
Vai ter uma parte de login na API?
Também fiquei em duvida em relação a isso, principalmente em delimitar o tempo do token.
Muito Bom!
quando faço requisição de todos os contatos, o retorno e isso, alguem sabe pq o metodo n ta definido?
NoMethodError (undefined method `contacts’ for #):
Sobre o versionamento, teremos por exemplo 10,20,30 pastas V30 para cada versão, duplicando pastas, codigo, o arquivo de routes vai ficar gordo. É assim mesmo ?
Olá, primeiramente ótimo artigo!
Estou tendo esse problema ao seguir os passos do postman na aula 3, já criei o emal, senha e recebi o token, adicionei nos headers mas continuo com o problema(Já estava acontecendo antes msm de adicionar o emal e token nos headers).
ActionController::RoutingError (undefined method ` before_action’ for Api::V1::ContactsController:Class
Did you mean? before_action):

Eu segui todos os passos e a aplicação roda localmente sem problemas, mas quando tento acessar pelo postman recebo o seguinte erro:
#<NameError: uninitialized constant ApplicationController>
Quando eu tento usar o postman recebo esse erro> > “error”: “You need to sign in or sign up before continuing.”
Olá, ótimo artigo.
Mesmo copiando e colando, estou recebendo este erro:
edsonlima@MacPro.local:~/projetos/rails/OneBitContacts$rails generate devise:install
/Users/edsonlima/.rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/activesupport-5.1.4/lib/active_support/dependencies.rb:286:in `load’: /Users/edsonlima/projetos/rails/OneBitContacts/config/initializers/rack_attack.rb:33: syntax error, unexpected end-of-input, expecting keyword_end (SyntaxError)