
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)
💻 • free link to dating sites no sign up
🙂 • dating site without payment
📱 • https://onebitcode.com/women-seeking-men-in-ohio/
🐦 • dating strangers
Nossos cursos:
🥇 • https://onebitcode.com/simple-rules-of-dating-my-teenage-daughter/
💎 • 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/
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)
E ai Edson, beleza?
Manda o link do github onde seu projeto está para eu dar uma olhada 🙂
Acredito que seja algum character extra
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.
Boa Fernando,
Valeu \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”
E ai cara, beleza?
Me chama por aqui que eu te dou um help: https://www.facebook.com/leonardo.scorzadesouza
Abraço
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!!
E ai Guilherme, beleza?
Opa, fico feliz que você tenha acompanhado o tutorial 🙂
Obrigado pelo feedback, ajustei o post nesse ponto.
Valeu \o/
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.
E ai Axel, beleza?
Quais problemas? 🙂
Muito bem explicado, parabéns,
Vai ter uma parte de login na API?
também gostaria foi uma parte que fiquei em duvida
Também fiquei em duvida em relação a isso, principalmente em delimitar o tempo do token.
Tem algum tutorial no OneBitCode, que mostre como integrar essa a API nesse tutorial com algum frontend?
Tem algum tutorial no OneBitCode, mostrando como integrar essa API com um Frontend?
Teria algum artigo mostrando com integrar essa api com o Front?
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 #):
Bom dia Ezequiel,
Verifique se o seu controller está igual ao da aula.
Grande abraço
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 ?
Alessandro, o normal é você acabar tendo 2 ou 3 versões no máximo (exp: a API do Google Maps está na versão 3 depois de anos), isso não será um problema 🙂
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.”
Excelente artigo