diff --git a/.gitignore b/.gitignore index 791326f..1dfe532 100644 --- a/.gitignore +++ b/.gitignore @@ -25,3 +25,5 @@ # Ignore master key for decrypting credentials and more. /config/master.key +# Siempre da conflictos +/db/schema.rb diff --git a/app/controllers/consensos_controller.rb b/app/controllers/consensos_controller.rb new file mode 100644 index 0000000..f188d52 --- /dev/null +++ b/app/controllers/consensos_controller.rb @@ -0,0 +1,27 @@ +# frozen_string_literal: true + +# Consensos +class ConsensosController < ApplicationController + # Podemos ver todos los consensos + def index + @consensos = Consenso.all.order(:created_at, :desc) + end + + # Podemos ver uno solo + def show + @consenso = Consenso.find(params[:id]) + return if @consenso + + render json: {}, status: :not_found + end + + # Podemos crear uno + def create + @consenso = Consenso.new(params.require(:consenso).permit(:titulo, :texto)) + + return if @consenso.save + + render json: { errors: @consenso.errors.full_messages }, + status: :unprocessable_entity + end +end diff --git a/app/controllers/posiciones_controller.rb b/app/controllers/posiciones_controller.rb new file mode 100644 index 0000000..4805acf --- /dev/null +++ b/app/controllers/posiciones_controller.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +# Las posiciones solo se pueden agregar a su consenso +class PosicionesController < ApplicationController + def create + @consenso = Consenso.find(params[:consenso_id]) + @posicion = consenso.try(:posiciones).try(:build, posicion_params) + + return if @posicion.try(:save) + + render json: {}, status: :not_found + end + + private + + def posicion_params + params.require(:posicion).permit(:estado, :comentario) + end +end diff --git a/app/models/consenso.rb b/app/models/consenso.rb new file mode 100644 index 0000000..d325372 --- /dev/null +++ b/app/models/consenso.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +# El consenso agrupa posiciones y textos +class Consenso < ApplicationRecord + # Es escrito por una pirata + belongs_to :pirata + # Agrupa muchas posiciones + has_many :posiciones +end diff --git a/app/models/pirata.rb b/app/models/pirata.rb index 41b45d0..9b929cd 100644 --- a/app/models/pirata.rb +++ b/app/models/pirata.rb @@ -2,7 +2,12 @@ # Las piratas son las usuarias empoderadas del miniloom class Pirata < ApplicationRecord - # Tiene una contraseña segura :P + # Puede proponer consensos + has_many :consensos + # Y tener posiciones + has_many :posiciones + + # Y además una contraseña segura :P has_secure_password # Una por correo validates :email, presence: true, uniqueness: true diff --git a/app/models/posicion.rb b/app/models/posicion.rb new file mode 100644 index 0000000..7d60042 --- /dev/null +++ b/app/models/posicion.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +# Una posición sobre un consenso +class Posicion < ApplicationRecord + # Tiene alguno de estos estados. + # + # TODO: Poder definirlos por configuración en lugar de hardcodearlos, + # pero al menos por ahora los podemos cambiar acá y no por todos lados + # como pasaba en Loomio + ESTADOS = %w[compromiso a_favor en_contra bloqueo indiferente].freeze + + # Es hecha por una pirata + belongs_to :pirata + # Sobre un consenso + belongs_to :consenso + + # Solo puede tener alguno de los estados definidos + validates :estado, inclusion: { in: Posicion::ESTADOS } +end diff --git a/app/views/consensos/_consenso.json.jbuilder b/app/views/consensos/_consenso.json.jbuilder new file mode 100644 index 0000000..2847808 --- /dev/null +++ b/app/views/consensos/_consenso.json.jbuilder @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +json.call(consenso, :id, :created_at, :titulo, :texto) + +json.posiciones consenso.posiciones, partial: 'posiciones/posicion', as: :posicion diff --git a/app/views/consensos/create.json.jbuilder b/app/views/consensos/create.json.jbuilder new file mode 100644 index 0000000..f1e4c6b --- /dev/null +++ b/app/views/consensos/create.json.jbuilder @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +json.partial! @consenso, as: :consenso diff --git a/app/views/consensos/index.json.jbuilder b/app/views/consensos/index.json.jbuilder new file mode 100644 index 0000000..a4c24ba --- /dev/null +++ b/app/views/consensos/index.json.jbuilder @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +json.consensos @consensos, partial: 'consensos/consenso', as: :consenso diff --git a/app/views/consensos/show.json.jbuilder b/app/views/consensos/show.json.jbuilder new file mode 100644 index 0000000..f1e4c6b --- /dev/null +++ b/app/views/consensos/show.json.jbuilder @@ -0,0 +1,3 @@ +# frozen_string_literal: true + +json.partial! @consenso, as: :consenso diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index dc84742..177631c 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -5,12 +5,10 @@ # Add new inflection rules using the following format. Inflections # are locale specific, and you may define rules for as many different # locales as you wish. All of these examples are active by default: -# ActiveSupport::Inflector.inflections(:en) do |inflect| -# inflect.plural /^(ox)$/i, '\1en' -# inflect.singular /^(ox)en/i, '\1' -# inflect.irregular 'person', 'people' -# inflect.uncountable %w( fish sheep ) -# end +ActiveSupport::Inflector.inflections(:en) do |inflect| + inflect.plural 'posicion', 'posiciones' + inflect.singular 'posiciones', 'posicion' +end # These inflection rules are supported but not enabled by default: # ActiveSupport::Inflector.inflections(:en) do |inflect| diff --git a/config/routes.rb b/config/routes.rb index 46f8e86..1e4c5dd 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,4 +3,9 @@ Rails.application.routes.draw do # No queremos un índice de piratas resources :piratas, only: %i[create] + # Podemos crear consensos pero no modificarlos + resources :consensos, only: %i[index show create] do + # Y solo le podemos agregar posiciones + resources :posiciones, only: %i[create] + end end diff --git a/db/migrate/20190405211246_create_consensos.rb b/db/migrate/20190405211246_create_consensos.rb new file mode 100644 index 0000000..6094df4 --- /dev/null +++ b/db/migrate/20190405211246_create_consensos.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +# Crear la tabla de consensos +class CreateConsensos < ActiveRecord::Migration[5.2] + def change + create_table :consensos do |t| + t.timestamps + t.belongs_to :pirata, index: true + t.string :titulo + t.text :texto + end + end +end diff --git a/db/migrate/20190405211514_create_posiciones.rb b/db/migrate/20190405211514_create_posiciones.rb new file mode 100644 index 0000000..6d97d40 --- /dev/null +++ b/db/migrate/20190405211514_create_posiciones.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Crear la tabla de posiciones +class CreatePosiciones < ActiveRecord::Migration[5.2] + def change + create_table :posiciones do |t| + t.timestamps + t.belongs_to :consenso, index: true + t.belongs_to :pirata, index: true + t.string :comentario + t.string :estado + end + end +end diff --git a/test/controllers/consensos_controller_test.rb b/test/controllers/consensos_controller_test.rb new file mode 100644 index 0000000..4643d02 --- /dev/null +++ b/test/controllers/consensos_controller_test.rb @@ -0,0 +1,38 @@ +# frozen_string_literal: true + +require 'test_helper' + +class ConsensosControllerTest < ActionDispatch::IntegrationTest + test 'se pueden mostrar' do + 2.times { create :consenso } + + get consensos_url, as: :json + body = JSON.parse(@response.body) + + assert_equal 2, body['consensos'].size + end + + test 'se puede ver uno solo' do + consenso = create :consenso + + get consenso_url(consenso), as: :json + body = JSON.parse(@response.body) + + assert_equal consenso.titulo, body['titulo'] + end + + test 'se pueden crear' do + post consensos_url, as: :json, params: { + consenso: { + titulo: 'hola', + texto: 'chau' + } + } + + body = JSON.parse(@response.body) + consenso = Consenso.find(body['id']) + + assert_equal 'hola', consenso.titulo + assert_equal 'chau', consenso.texto + end +end diff --git a/test/controllers/posiciones_controller_test.rb b/test/controllers/posiciones_controller_test.rb new file mode 100644 index 0000000..4c12fbb --- /dev/null +++ b/test/controllers/posiciones_controller_test.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +require 'test_helper' + +class PosicionesControllerTest < ActionDispatch::IntegrationTest + # test "the truth" do + # assert true + # end +end diff --git a/test/factories/consensos.rb b/test/factories/consensos.rb new file mode 100644 index 0000000..e176580 --- /dev/null +++ b/test/factories/consensos.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :consenso do + pirata + titulo { 'Estamos a favor de la despenalización del aborto' } + texto { '...' } + end +end diff --git a/test/factories/posiciones.rb b/test/factories/posiciones.rb new file mode 100644 index 0000000..953ebc8 --- /dev/null +++ b/test/factories/posiciones.rb @@ -0,0 +1,10 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :posicion do + pirata + consenso + + estado { Posicion::ESTADOS.sample } + end +end diff --git a/test/models/consenso_test.rb b/test/models/consenso_test.rb new file mode 100644 index 0000000..ef3e14a --- /dev/null +++ b/test/models/consenso_test.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'test_helper' + +class ConsensoTest < ActiveSupport::TestCase + test 'se pueden crear' do + consenso = create :consenso + + assert_equal true, consenso.valid? + end +end diff --git a/test/models/posicion_test.rb b/test/models/posicion_test.rb new file mode 100644 index 0000000..1906894 --- /dev/null +++ b/test/models/posicion_test.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +require 'test_helper' + +class PosicionTest < ActiveSupport::TestCase + test 'se pueden crear' do + posicion = create :posicion + + assert_equal true, posicion.valid? + end +end