barcas! al abordaje!

This commit is contained in:
fauno 2019-08-03 13:23:52 -03:00
parent d669875815
commit ac21341d49
No known key found for this signature in database
GPG key ID: 456032D717A4CD9C
18 changed files with 201 additions and 41 deletions

View file

@ -6,17 +6,18 @@
class ConsensosController < ApplicationController
# Para cualquier acción necesitamos autenticación
before_action :authenticate!
before_action :find_barca!
# GET /consensos
# GET /barcas/:barca_id/consensos
#
# Podemos ver todos los consensos
# Podemos ver todos los consensos de una barca
#
# @return [Array] [ consensos ]
def index
@consensos = Consenso.all.order(:created_at, :desc)
@consensos = @barca.consensos.order(:created_at, :desc)
end
# GET /consensos/:id
# GET /barcas/:barca_id/consensos/:id
#
# Podemos ver uno solo sabiendo su ID
#
@ -26,13 +27,13 @@ class ConsensosController < ApplicationController
# pirata: @pirata,
# posiciones: [] }
def show
@consenso = Consenso.find(params[:id])
@consenso = @barca.consensos.find(params[:id])
return if @consenso
render json: {}, status: :not_found
end
# POST /consensos
# POST /barcas/:barca_id/consensos
#
# Podemos crear uno, enviando un hash con todas las propiedades
#
@ -42,8 +43,8 @@ class ConsensosController < ApplicationController
# pirata: @pirata,
# posiciones: [] }
def create
@consenso = current_pirata.consensos
.new(params.require(:consenso).permit(:titulo, :texto))
@consenso = current_pirata.consensos.new(consenso_params)
@consenso.barca = @barca
if @consenso.save
render status: :created
@ -53,7 +54,7 @@ class ConsensosController < ApplicationController
end
end
# DELETE /consensos/:id
# DELETE /barcas/:barca_id/consensos/:id
#
# Eliminar un consenso, solo si no tiene posiciones!
#
@ -63,7 +64,7 @@ class ConsensosController < ApplicationController
# posiciones: [] }
def destroy
begin
@consenso = Consenso.find(params[:id])
@consenso = @barca.consensos.find(params[:id])
rescue ActiveRecord::RecordNotFound
render json: {}, status: :not_found
return
@ -75,4 +76,16 @@ class ConsensosController < ApplicationController
render json: {}, status: :unprocessable_entity
end
end
private
# Encuentra la barca en los parámetros
def find_barca!
@barca = Barca.find(params[:barca_id])
end
# Parámetros permitidos
def consenso_params
params.require(:consenso).permit(:titulo, :texto)
end
end

View file

@ -8,8 +8,9 @@
class PosicionesController < ApplicationController
# Necesitamos autenticarnos
before_action :authenticate!
before_action :find_barca!
# POST /consensos/:consenso_id/posiciones
# POST /barcas/:barca_id/consensos/:consenso_id/posiciones
#
# Crea una posición dentro de un consenso
#
@ -18,7 +19,7 @@ class PosicionesController < ApplicationController
# @return [Hash] { id: @int, estado: @string, comentario: @string,
# pirata: @pirata }
def create
@consenso = Consenso.find(params[:consenso_id])
@consenso = @barca.consensos.find(params[:consenso_id])
@posicion = @consenso.try(:posiciones).try(:build, posicion_params)
@posicion.try(:pirata=, current_pirata)
@ -35,4 +36,8 @@ class PosicionesController < ApplicationController
def posicion_params
params.require(:posicion).permit(:estado, :comentario)
end
def find_barca!
@barca = Barca.find(params[:barca_id])
end
end

16
app/models/barca.rb Normal file
View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
# Las barcas agrupan consensos y piratas alrededor de un tema específico
# o relación de afinidad
class Barca < ApplicationRecord
# Tiene muchos consensos
has_many :consensos
# En realidad debería tener una sola tripulación que traiga muchas
# piratas, pero rails es así
has_many :tripulaciones, dependent: :destroy
has_many :piratas, through: :tripulaciones
validates_uniqueness_of :nombre
validates_presence_of :descripcion
end

View file

@ -7,4 +7,6 @@ class Consenso < ApplicationRecord
belongs_to :pirata
# Agrupa muchas posiciones
has_many :posiciones
# Pertenece a una barca
belongs_to :barca
end

View file

@ -7,6 +7,10 @@ class Pirata < ApplicationRecord
# Y tener posiciones
has_many :posiciones
# Puede participar en barcas
has_many :tripulaciones
has_many :barcas, through: :tripulaciones
# Y además una contraseña segura :P
has_secure_password
# Una por correo

View file

@ -0,0 +1,7 @@
# frozen_string_literal: true
# La tripulación de una barca
class Tripulacion < ApplicationRecord
belongs_to :barca
belongs_to :pirata
end

View file

@ -10,6 +10,8 @@ ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.singular 'posiciones', 'posicion'
inflect.plural 'pirata', 'piratas'
inflect.singular 'piratas', 'pirata'
inflect.plural 'tripulacion', 'tripulaciones'
inflect.singular 'tripulaciones', 'tripulacion'
end
# These inflection rules are supported but not enabled by default:

View file

@ -4,9 +4,12 @@ Rails.application.routes.draw do
get '/piratas/yo', to: 'piratas#yo'
# No queremos un índice de piratas
resources :piratas, only: %i[create]
# Podemos crear barcas y dentro de ellas consensos
resources :barcas, only: %i[index show create update destroy] do
# Podemos crear consensos pero no modificarlos
resources :consensos, only: %i[index show create destroy] do
# Y solo le podemos agregar posiciones
resources :posiciones, only: %i[create]
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
# Crear las barcas
class CreateBarcas < ActiveRecord::Migration[5.2]
def change
create_table :barcas do |t|
t.timestamps
t.string :nombre, unique: true
t.text :descripcion
end
end
end

View file

@ -0,0 +1,12 @@
# frozen_string_literal: true
# Las piratas abordan barcas a través de tripulaciones
class CreateTripulaciones < ActiveRecord::Migration[5.2]
def change
create_table :tripulaciones do |t|
t.timestamps
t.belongs_to :barca, index: true
t.belongs_to :pirata, index: true
end
end
end

View file

@ -0,0 +1,8 @@
# frozen_string_literal: true
# Los consensos pertenecen a barcas
class AddBarcaToConsenso < ActiveRecord::Migration[5.2]
def change
add_belongs_to :consensos, :barca, index: true
end
end

View file

@ -0,0 +1,21 @@
# frozen_string_literal: true
# Si no hay una barca, creamos una asamblea general!
class AsambleaGeneral < ActiveRecord::Migration[5.2]
def up
return if Barca.all.count.positive?
barca = Barca.create(nombre: 'Asamblea General',
descripcion: 'En la asamblea general tomamos todas las decisiones que no pasan por barcas.')
Pirata.all.find_each do |pirata|
barca.piratas << pirata
end
barca.save
end
def down
Barca.find_by(nombre: 'Asamblea General').destroy
end
end

View file

@ -2,6 +2,7 @@
class ConsensosControllerTest < ActionDispatch::IntegrationTest
setup do
@barca = create :barca
@pirata = create :pirata
@auth = { Authorization: ActionController::HttpAuthentication::Basic
.encode_credentials(@pirata.email, @pirata.password) }
@ -9,10 +10,10 @@ class ConsensosControllerTest < ActionDispatch::IntegrationTest
test 'se pueden mostrar' do
2.times do
create :consenso
create :consenso, barca: @barca
end
get consensos_url, as: :json, headers: @auth
get barca_consensos_url(@barca), as: :json, headers: @auth
body = JSON.parse(@response.body)
assert_equal 200, @response.status
@ -21,7 +22,7 @@ class ConsensosControllerTest < ActionDispatch::IntegrationTest
test 'al mostrar solo se ven las posiciones resumidas' do
2.times do
consenso = create :consenso
consenso = create :consenso, barca: @barca
pirata = create :pirata
3.times do
@ -29,7 +30,7 @@ class ConsensosControllerTest < ActionDispatch::IntegrationTest
end
end
get consensos_url, as: :json, headers: @auth
get barca_consensos_url(@barca), as: :json, headers: @auth
body = JSON.parse(@response.body)
body['consensos'].each do |consenso|
@ -40,7 +41,9 @@ class ConsensosControllerTest < ActionDispatch::IntegrationTest
test 'se puede ver uno solo' do
consenso = create :consenso, con_posiciones: 2
get consenso_url(consenso), as: :json, headers: @auth
get barca_consenso_url(consenso.barca, consenso),
as: :json,
headers: @auth
body = JSON.parse(@response.body)
assert_equal 200, @response.status
@ -49,26 +52,22 @@ class ConsensosControllerTest < ActionDispatch::IntegrationTest
end
test 'al ver uno solo se ve todo el historial de posiciones' do
consenso = create :consenso
consenso = create :consenso, barca: @barca
pirata = create :pirata
3.times do
create :posicion, consenso: consenso, pirata: pirata
end
get consenso_url(consenso), as: :json, headers: @auth
get barca_consenso_url(@barca, consenso), as: :json, headers: @auth
body = JSON.parse(@response.body)
assert_equal 3, body['posiciones'].size
end
test 'se pueden crear' do
post consensos_url, as: :json, headers: @auth, params: {
consenso: {
titulo: 'hola',
texto: 'chau'
}
}
post barca_consensos_url(@barca), as: :json, headers: @auth,
params: { consenso: { titulo: 'hola', texto: 'chau' } }
assert_equal 201, @response.status
@ -80,9 +79,10 @@ class ConsensosControllerTest < ActionDispatch::IntegrationTest
end
test 'se pueden borrar si están vacíos' do
consenso = create :consenso
consenso = create :consenso, barca: @barca
delete consenso_url(consenso), as: :json, headers: @auth
delete barca_consenso_url(@barca, consenso),
as: :json, headers: @auth
assert_equal 200, @response.status
@ -91,10 +91,11 @@ class ConsensosControllerTest < ActionDispatch::IntegrationTest
end
test 'no se pueden borrar si no están vacíos' do
consenso = create :consenso
consenso = create :consenso, barca: @barca
create :posicion, consenso: consenso
delete consenso_url(consenso), as: :json, headers: @auth
delete barca_consenso_url(@barca, consenso),
as: :json, headers: @auth
assert_equal 422, @response.status
end

View file

@ -4,22 +4,19 @@ require 'test_helper'
class PosicionesControllerTest < ActionDispatch::IntegrationTest
setup do
@barca = create :barca
@pirata = create :pirata
@auth = { Authorization: ActionController::HttpAuthentication::Basic
.encode_credentials(@pirata.email, @pirata.password) }
end
test 'se pueden crear' do
consenso = create :consenso
consenso = create :consenso, barca: @barca
estado = Posicion::ESTADOS.sample
post consenso_posiciones_url(consenso), as: :json, headers: @auth,
params: {
posicion: {
estado: estado,
comentario: 'porque me place'
}
}
post barca_consenso_posiciones_url(@barca, consenso),
as: :json, headers: @auth,
params: { posicion: { estado: estado, comentario: 'porque me place' } }
assert_equal 201, @response.status

16
test/factories/barca.rb Normal file
View file

@ -0,0 +1,16 @@
# frozen_string_literal: true
FactoryBot.define do
factory :barca do
nombre { SecureRandom.hex }
descripcion { SecureRandom.hex }
transient do
tripulacion { 0 }
end
after :create do |barca, evaluator|
create_list(:tripulacion, evaluator.tripulacion, barca: barca)
end
end
end

View file

@ -2,6 +2,7 @@
FactoryBot.define do
factory :consenso do
barca
pirata
titulo { 'Estamos a favor de la despenalización del aborto' }
texto { '...' }

View file

@ -0,0 +1,8 @@
# frozen_string_literal: true
FactoryBot.define do
factory :tripulacion do
barca
pirata
end
end

32
test/models/barca_test.rb Normal file
View file

@ -0,0 +1,32 @@
# frozen_string_literal: true
class BarcaTest < ActiveSupport::TestCase
test 'se pueden crear' do
barca = create :barca
assert_equal true, barca.valid?
end
test 'pueden tener tripulacion' do
barca = create :barca, tripulacion: 3
assert_equal 3, barca.tripulaciones.count
assert_equal 3, barca.piratas.count
end
test 'el nombre tiene que ser único' do
create :barca, nombre: 'hola'
barca = build :barca, nombre: 'hola'
assert barca.invalid?
end
test 'al eliminar la barca se elimina su tripulación' do
barca = create :barca, tripulacion: 3
assert barca.destroy
assert_equal 3, Pirata.all.count
assert Tripulacion.all.count.zero?
end
end