La autenticación bien probada evita regresiones y errores silenciosos. Aquí se valida, paso a paso, cómo asegurar en Rails que solo usuarios autenticados puedan crear y actualizar, cómo responder con códigos correctos y cómo refactorizar la autenticación en un concern reutilizable. El foco está en pruebas claras, estados HTTP precisos y manejo explícito de excepciones.
¿Cómo validar la creación con autenticación en Rails?
Para creación se definen dos contextos: con autenticación válida y sin autenticación. Se envían parámetros anidados bajo la clave post, tal como exige el controlador en su método de parámetros fuertes. La verificación cubre el contenido del payload y el código de estado.
Con autenticación: se debe poder crear y responder con created.
Sin autenticación: no debe crear y debe responder unauthorized.
Los parámetros de creación incluyen: title, content y published.
El payload esperado incluye: id, title, content, published y author.
¿Qué parámetros y headers usar en el request?
Parám: enviar bajo la clave post.
Headers: usar auth headers válidos.
Método: POST a la ruta de posts.
# RSpeccontext 'with valid auth'do let(:create_params)do{post:{title:'title',content:'...',published:true}}end it 'crea el post y responde created'do post '/posts',params: create_params,headers: auth_headers
expect(payload).to include('id','title','content','published','author') expect(response).to have_http_status(:created)endendcontext 'without authentication'do it 'rechaza la creación con unauthorized'do post '/posts',params:{post:{title:'title',content:'...',published:true}} expect(payload).to include('error') expect(response).to have_http_status(:unauthorized)endend
¿Qué validar en el payload y response?
Contenido: incluir claves id, title, content, published y author.
Errores: incluir error si falta autenticación.
Estados: usar created y unauthorized según el caso.
¿Qué pruebas aseguran la actualización y control de acceso?
La actualización replica la estructura de creación, con énfasis en control de acceso. Con autenticación se puede actualizar el propio post; intentar actualizar el post de otro usuario debe responder not found. El estado esperado para éxito es ok.
Caso propio: actualizar vía PUT el recurso del usuario autenticado.
Caso ajeno: no permitir y responder not found.
Sin autenticación: ya cubierto por las validaciones de creación, evitar redundancia.
¿Cómo probar el update del propio post?
Ruta: PUT a /posts/:id del usuario autenticado.
Parámetros: usar update params con la misma estructura.
Validaciones: coincidir id y responder ok.
context "when updating user's post"do let(:update_params)do{post:{title:'new title',content:'...',published:true}}end it 'actualiza y responde ok'do put "/posts/#{user_post.id}",params: update_params,headers: auth_headers
expect(payload).to include('id','title','content','published','author') expect(payload['id']).to eq(user_post.id) expect(response).to have_http_status(:ok)endend
¿Cómo bloquear el update de otro usuario?
Ruta: PUT a /posts/:id de un tercero.
Resultado: payload con error y estado not found.
context "when updating other user's post"do let(:update_params)do{post:{title:'any',content:'...',published:true}}end it 'rechaza con not found'do put "/posts/#{other_user_post.id}",params: update_params,headers: auth_headers
expect(payload).to include('error') expect(response).to have_http_status(:not_found)endend
¿Cómo manejar excepciones y reutilizar autenticación con concerns?
Al buscar posts con find, si no existe el registro, Rails lanza ActiveRecord::RecordNotFound. Sin manejarla, un capturador genérico devuelve 500. Se debe capturar explícitamente y responder 404 not found. Además, para evitar duplicación, el método de autenticación se mueve a un concern llamado Secured y se incluye en los controladores que lo requieran.
Excepción: ActiveRecord::RecordNotFound debe mapear a not found.
Reutilización: extraer authenticate_user a un module compartido.
Limpieza: eliminar pruebas antiguas de creación y actualización sin autenticación, mantener listado y lectura de publicados.
¿Cómo capturar ActiveRecord::RecordNotFound y responder 404?
# ApplicationControllerrescue_from ActiveRecord::RecordNotFound do render json:{error:'Not found'},status::not_foundend
¿Cómo extraer authenticate_user a un concern reutilizable?
# app/controllers/concerns/secured.rbmoduleSecureddefauthenticate_user# implementación movida desde el controlador.endend# posts_controller.rbclassPostsController< ApplicationController
include Secured
# accionesend
¿Te gustaría compartir cómo estructuras tus contexts y expectativas para mantener las pruebas legibles y confiables?