ruby Sinatra API REST CRUD

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ruby Sinatra API REST CRUD相关的知识,希望对你有一定的参考价值。

class Cliente
  include DataMapper::Resource

  property :id, Serial
  property :nombre, String
  property :edad, Integer
  property :created_at, DateTime
  property :updated_at, DateTime

  validates_presence_of :nombre
end
# ver notas en notas.txt
require 'sinatra'
require 'sinatra/reloader' if development?
require 'sinatra/json'
require 'bundler'
Bundler.require
require './cliente'

DataMapper.setup(:default, 'sqlite::memory')
#DataMapper.setup(:default, "sqlite3://#{Dir.pwd}/development.sqlite3")
DataMapper.finalize
DataMapper.auto_migrate!

# Autenticacion http simple - http://www.sinatrarb.com/faq.html#auth
#use Rack::Auth::Basic, "Restricted Area" do |username, password|
#  username == 'admin' and password == 'admin'
#end

# curl http://localhost:4567
get '/' do
  "Hola Sinatra"
end

# curl http://localhost:4567/clientes
get '/clientes' do
  clientes = Cliente.all
  clientes.to_json
end

# version que puede retornar json o html
# si se accede por browser, retorna html
# para llamarlo como API, desde curl seria asi:
# curl -H "Accept:application/json" http://localhost:4567/clientes
get '/clientes' do
  clientes = Cliente.all
  
  respond_to do |format|
    format.html { erb :clientes }    # para este ejemplo crear views/clientes.erb   
    format.json { clientes.to_json }
  end
end

# curl http://localhost:4567/clientes/:id
get '/clientes/:id' do
  cliente = Cliente.get params[:id]

  if cliente
    cliente.to_json
  else
    status 404
    json "Cliente no existe"
  end
end

# curl -d "" http://localhost:4567/clientes   (sin datos si quiero error)
# curl -d "cliente[nombre]=Pepe&cliente[edad]=40" http://localhost:4567/clientes
post '/clientes' do
  cliente = Cliente.new params[:cliente]

  if cliente.save
    status 201      # resource created successfully
    json "Cliente creado"
  else
    status 500
    json cliente.errors.full_messages
  end
end

# curl -X PUT -d "cliente[nombre]=PepeX" http://localhost:4567/clientes/:id
put '/clientes/:id' do
  cliente = Cliente.get params[:id]

  if cliente.update params[:cliente]
    status 200
    json "Cliente actualizado"
  else
    status 500
    json cliente.errors.full_messages
  end
end

# curl -X DELETE http://localhost:4567/clientes/:id
delete '/clientes/:id' do
  cliente = Cliente.get params[:id]

  if cliente.destroy
    status 200
    json "Cliente removido"
  else
    status 500
    json "Hubo en problema para remover al cliente"
  end
end
Este ejemplo lo hice principalmente basandome en este video:  
https://www.youtube.com/watch?v=d4lxXu7UOwg&t=114s

No lo segui al pie de la letra, y le fui agregando cosas que encontre en otros lados.  
Por ejemplo le agregue un hook 'before' para que todos los endpoints los trate como json, le agregue el reloader en modo development, etc

--------------------------------------------------------------------------------
Deje un bloque comentado con autenticacion http basica.  
*Faltaria agregarle un ejemplo de curl pasando credenciales*.  

--------------------------------------------------------------------------------
Si bien el hook 'before' dice que todos los endpoints retornan json, en el endpoint '/' retorno solo un string y funciona bien, retornando el mensaje

--------------------------------------------------------------------------------
`Bundler.require` hace un 'require' de todas las gemas del Gemfile

--------------------------------------------------------------------------------
El `require './cliente'` debe ir despues de `Bundler.require` porque este es el que incluye las gemas necesarias, en este caso el DataMapper

--------------------------------------------------------------------------------
La ejecucion de `DataMapper.auto_migrate!` en este caso se puede hacer en el mismo fuente porque como la base esta en memoria, de todos modos se pierde cuando se baja el server.  
Pero si la base esta en archivo, el `auto_migrate!` debe ejecutarse solo una vez, ya que provoca el reset de la base.  
Esto se puede hacer entrando por 'pry', ejecutar `require './app'` y luego el `DataMapper.auto_migrate!`.  

Deje una linea comentada con la linea *setup* que se usaria para que la base de datos este en un archivo.

--------------------------------------------------------------------------------
En la linea: `cliente = Cliente.new params[:cliente]` la notacion `[:cliente]` se refiere al nombre del 'hash' que espera recibir.  
Se ve en la invocacion que podemos hacer con curl

  `curl -d "cliente[nombre]=Pepe&cliente[edad]=40" http://localhost:4567/clientes`

--------------------------------------------------------------------------------
En el metodo 'delete' si hay un error en la operacion, se retorna un string en lugar de los mensajes del objeto Cliente.  
Esto es porque en este caso no se produjeron errores de validacion, por lo tanto no tiene sentido pasar los errores del objeto de datos.

# - si no tenes bundler: gem install bundler
source 'https://rubygems.org'
gem 'sinatra', ">=1.0"
gem 'sinatra-contrib'
gem 'rake'
gem 'data_mapper'
gem 'dm-core'
gem 'dm-sqlite-adapter'
gem 'dm-timestamps'
gem 'dm-validations'
gem 'dm-aggregates'
gem 'dm-migrations'

以上是关于ruby Sinatra API REST CRUD的主要内容,如果未能解决你的问题,请参考以下文章

restclient为啥加不上heads

ruby Twilio Sinatra

ruby sinatra_test.rb

ruby Sinatra路线版本.rb

ruby Sinatra演示应用程序 - 比特币价格

在google appengine上部署ruby + sinatra应用程序