From 10ed81a3f5890ae7a118d1d35a17f34fc09b8aa3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C3=A0=20Mattos?= Date: Sun, 28 Jun 2026 11:10:45 -0300 Subject: [PATCH 1/3] refactor: reduz complexidade dos controllers --- app/controllers/dashboards_controller.rb | 72 +++++++----- app/controllers/formularios_controller.rb | 89 ++++++++++----- .../importer/academic_data_importer.rb | 106 ++++++++++-------- app/views/dashboards/admin.html.erb | 1 - 4 files changed, 161 insertions(+), 107 deletions(-) diff --git a/app/controllers/dashboards_controller.rb b/app/controllers/dashboards_controller.rb index 4426a400e7..31e59dae6b 100644 --- a/app/controllers/dashboards_controller.rb +++ b/app/controllers/dashboards_controller.rb @@ -3,58 +3,72 @@ class DashboardsController < ApplicationController before_action :require_login - layout "admin_layout", only: [ :admin, :admin_gerenciamento, :admin_avaliacao ] - # tela de admin def admin end - # tela de gerenciamento def admin_gerenciamento - @turmas = Turma.all + @turmas = Turma.all @discentes = Discente.all - @docentes = Docente.all + @docentes = Docente.all end - # importação do json def importar_json - # codigo de auxilio - if params["json"].blank? - puts "ERRO: O parâmetro 'json' veio vazio!" - flash[:error] = "Por favor, selecione um arquivo JSON." - redirect_to admin_gerenciamento_dashboard_path and return - end - - puts "Arquivo recebido com sucesso: #{params["json"].original_filename}" + return redirecionar_json_vazio if json_vazio? - # Chama o service - resultado = Importer::AcademicDataImporter.import!(params["json"]) + registrar_arquivo_recebido - if resultado - puts "SUCESSO: O Service Object terminou sem erros." + if importar_dados_json flash[:success] = "JSON importado com sucesso!" else - puts "AVISO: O Service retornou falso." + flash[:alert] = "Ocorreu um problema ao importar o JSON." end - redirect_to admin_gerenciamento_dashboard_path - - rescue => e - puts "EXCEÇÃO CAPTURADA NO CONTROLLER: #{e.message}" - puts e.backtrace.first(2) - flash[:error] = "Ocorreu um erro na importação: #{e.message}" redirect_to admin_gerenciamento_dashboard_path + rescue StandardError => e + tratar_erro_importacao(e) end - + def admin_avaliacao + end + def discente + end + private - # tela de avaliações - def admin_avaliacao + def json_vazio? + params[:json].blank? end - def discente + def redirecionar_json_vazio + puts "ERRO: O parâmetro 'json' veio vazio!" + flash[:error] = "Por favor, selecione um arquivo JSON." + redirect_to admin_gerenciamento_dashboard_path + end + + def registrar_arquivo_recebido + puts "Arquivo recebido com sucesso: #{params[:json].original_filename}" + end + + def importar_dados_json + resultado = Importer::AcademicDataImporter.import!(params[:json]) + + if resultado + puts "SUCESSO: O Service Object terminou sem erros." + true + else + puts "AVISO: O Service retornou falso." + false + end + end + + def tratar_erro_importacao(erro) + puts "EXCEÇÃO CAPTURADA NO CONTROLLER: #{erro.message}" + puts erro.backtrace.first(2) + + flash[:error] = "Ocorreu um erro na importação: #{erro.message}" + redirect_to admin_gerenciamento_dashboard_path end end diff --git a/app/controllers/formularios_controller.rb b/app/controllers/formularios_controller.rb index 7982e51565..4d79385153 100644 --- a/app/controllers/formularios_controller.rb +++ b/app/controllers/formularios_controller.rb @@ -1,66 +1,93 @@ -# app/controllers/formularios_controller.rb class FormulariosController < ApplicationController before_action :exigir_discente! before_action :set_formulario, only: [ :show ] - # GET /formularios def index @turmas = discente_atual.turmas - turmas_ids = discente_atual.turmas.pluck(:id) - respondidos_ids = discente_atual.envio_formularios.pluck(:formulario_id) - base = Formulario.where(turma_id: turmas_ids).includes(:turma, :template) - - @formularios_pendentes = formularios_pendentes(base, respondidos_ids) - @formularios_respondidos = formularios_respondidos(base) - @formularios_fechados = formularios_fechados(base, respondidos_ids) + @formularios_pendentes = formularios_pendentes + @formularios_respondidos = formularios_respondidos + @formularios_fechados = formularios_fechados end - # GET /formularios/:id def show - if discente_atual.ja_respondeu?(@formulario) - redirect_to minha_resposta_formulario_path(@formulario), - notice: "Você já respondeu este formulário." - return - end - - return redirect_to formularios_path, alert: "O prazo para responder este formulário já encerrou." unless @formulario.aberto? - return redirect_to formularios_path, alert: "Você não tem acesso a este formulário." unless discente_atual.turmas.include?(@formulario.turma) + return redirect_to_minha_resposta if formulario_respondido? + return redirect_formulario_fechado unless @formulario.aberto? + return redirect_sem_acesso_formulario unless discente_tem_acesso_ao_formulario? @questoes = @formulario.questoes.includes(questao_template: :opcao_questoes) end - # GET /formularios/:id/minha_resposta def minha_resposta @formulario = Formulario.find(params[:id]) - @envio = discente_atual.envio_formularios.find_by(formulario: @formulario) + @envio = discente_atual.envio_formularios.find_by(formulario: @formulario) - return redirect_to formularios_path, alert: "Você ainda não respondeu este formulário." unless @envio - return redirect_to formularios_path, alert: "Você não tem acesso a este formulário." unless discente_atual.turmas.include?(@formulario.turma) + return redirect_sem_resposta unless @envio + return redirect_sem_acesso_formulario unless discente_atual.turmas.include?(@formulario.turma) @respostas = @envio.respostas.includes(questao: { questao_template: :opcao_questoes }) end private + def turmas_ids + @turmas_ids ||= discente_atual.turmas.pluck(:id) + end + + def respondidos_ids + @respondidos_ids ||= discente_atual.envio_formularios.pluck(:formulario_id) + end + + def formularios_base + @formularios_base ||= Formulario.where(turma_id: turmas_ids).includes(:turma, :template) + end + + def formularios_pendentes + formularios_base.abertos.where.not(id: respondidos_ids).order(prazo: :asc) + end + + def formularios_respondidos + formularios_base + .joins(:envio_formularios) + .where(envio_formularios: { discente_id: discente_atual.id }) + .order("envio_formularios.enviado_em desc") + end + + def formularios_fechados + formularios_base.fechados.where.not(id: respondidos_ids).order(prazo: :desc) + end + def set_formulario @formulario = Formulario.find(params[:id]) rescue ActiveRecord::RecordNotFound redirect_to formularios_path, alert: "Formulário não encontrado." and return end - def formularios_pendentes(base, respondidos_ids) - base.abertos.where.not(id: respondidos_ids).order(prazo: :asc) + def formulario_respondido? + discente_atual.ja_respondeu?(@formulario) end - def formularios_respondidos(base) - base - .joins(:envio_formularios) - .where(envio_formularios: { discente_id: discente_atual.id }) - .order("envio_formularios.enviado_em desc") + def redirect_to_minha_resposta + redirect_to minha_resposta_formulario_path(@formulario), + notice: "Você já respondeu este formulário." + end + + def redirect_formulario_fechado + redirect_to formularios_path, + alert: "O prazo para responder este formulário já encerrou." + end + + def redirect_sem_acesso_formulario + redirect_to formularios_path, + alert: "Você não tem acesso a este formulário." + end + + def redirect_sem_resposta + redirect_to formularios_path, + alert: "Você ainda não respondeu este formulário." end - def formularios_fechados(base, respondidos_ids) - base.fechados.where.not(id: respondidos_ids).order(prazo: :desc) + def discente_tem_acesso_ao_formulario? + discente_atual.turmas.include?(@formulario.turma) end end diff --git a/app/services/importer/academic_data_importer.rb b/app/services/importer/academic_data_importer.rb index 6355c0fd42..db3cd85695 100644 --- a/app/services/importer/academic_data_importer.rb +++ b/app/services/importer/academic_data_importer.rb @@ -9,16 +9,17 @@ def self.import!(upload_file) ActiveRecord::Base.transaction do + departamento = Departamento.find_or_create_by!(nome: "Ciência da Computação") unique_turmas = data_hash.uniq { |t| [ t["code"], t["classCode"], t["semester"] ] } turma_objects = unique_turmas.map do |t| - Turma.new(codigo: t["code"], turma: t["classCode"], semestre: t["semester"], departamento: "Ciência da Computação") + Turma.new(codigo: t["code"], nome: t["classCode"], semestre: t["semester"], departamento: departamento) end # duplicação de objetos Turma.import turma_objects, on_duplicate_key_ignore: true, validate: false - turmas_hash = Turma.all.pluck(:codigo, :turma, :semestre, :id).each_with_object({}) do |(codigo, turma, semestre, id), hash| - hash["#{codigo}-#{turma}-#{semestre}"] = id + turmas_hash = Turma.all.pluck(:codigo, :nome, :semestre, :id).each_with_object({}) do |(codigo, nome, semestre, id), hash| + hash["#{codigo}-#{nome}-#{semestre}"] = id end # armazenar os discentes e docentes @@ -40,72 +41,85 @@ def self.import!(upload_file) raw_docentes << d_user.merge("turma_id" => turma_id) end end - + unique_discentes = raw_discentes.uniq { |d| d["matricula"] } unique_docentes = raw_docentes.uniq { |d| d["email"] } - discente_objects = unique_discentes.map do |members| - Discente.new( - nome: members["nome"]&.downcase, - curso: members["curso"]&.downcase, - matricula: members["matricula"], - usuario: members["usuario"], - formacao: members["formacao"]&.downcase, - ocupacao: members["ocupacao"]&.downcase, - email: members["email"]&.downcase, - turma_id: members["turma_id"] - ) - end - Discente.import discente_objects, on_duplicate_key_ignore: true, validate: false - - users_discente_objects = unique_discentes.map do |members| - User.new( + usuarios_discente_objects = unique_discentes.map do |members| + Usuario.new( + login: members["matricula"], nome: members["nome"]&.downcase, - matricula: members["matricula"], email: members["email"], - perfil: "Discente", + perfil: :discente, password: "123456", password_confirmation: "123456", primeiro_acesso: false ) - end - User.import users_discente_objects, on_duplicate_key_ignore: true, validate: false + Usuario.import usuarios_discente_objects, on_duplicate_key_ignore: true, validate: false - emails_importados = users_discente_objects.map(&:email) - usuarios_salvos = User.where(email: emails_importados) + emails_importados = usuarios_discente_objects.map(&:email) + usuarios_salvos = Usuario.where(email: emails_importados) + usuarios_por_email = usuarios_salvos.index_by(&:email) - usuarios_salvos.each do |usuario| - UsuarioMailer.email_primeiro_acesso(usuario).deliver_later - end + discente_objects = unique_discentes.filter_map do |members| + usuario = usuarios_por_email[members["email"]] + next unless usuario - docente_objects = unique_docentes.map do |members| - Docente.new( - nome: members["nome"]&.downcase, - departamento: members["departamento"]&.downcase, - usuario: members["usuario"], - formacao: members["formacao"]&.downcase, - ocupacao: members["ocupacao"]&.downcase, - email: members["email"]&.downcase, - turma: members["turma_id"] + Discente.new( + usuario: usuario, + matricula: members["matricula"], + curso: members["curso"]&.downcase ) end - Docente.import docente_objects, on_duplicate_key_ignore: true, validate: false + Discente.import discente_objects, on_duplicate_key_ignore: true, validate: false - users_docente_objects = unique_docentes.map do |members| - User.new( + matricula_objects = unique_discentes.filter_map do |members| + usuario = usuarios_por_email[members["email"]] + discente = Discente.find_by(usuario: usuario) + turma_id = members["turma_id"] + + next unless discente && turma_id + + Matricula.new(discente: discente, turma_id: turma_id) + end + Matricula.import matricula_objects, on_duplicate_key_ignore: true, validate: false + + usuarios_salvos.each do |usuario| + UserMailer.primeiro_acesso(usuario).deliver_later + end + + usuarios_docente_objects = unique_docentes.map do |members| + Usuario.new( + login: members["email"], nome: members["nome"]&.downcase, - matricula: members["email"], email: members["email"], - perfil: "Docente", + perfil: :docente, password: "123456", password_confirmation: "123456", primeiro_acesso: false ) end - - User.import users_docente_objects, on_duplicate_key_ignore: true, validate: false + Usuario.import usuarios_docente_objects, on_duplicate_key_ignore: true, validate: false + + docentes_por_email = Usuario.where(email: usuarios_docente_objects.map(&:email)).index_by(&:email) + + docente_objects = unique_docentes.filter_map do |members| + usuario = docentes_por_email[members["email"]] + next unless usuario + + Docente.new(usuario: usuario, departamento: departamento) + end + Docente.import docente_objects, on_duplicate_key_ignore: true, validate: false + + unique_docentes.each do |members| + usuario = docentes_por_email[members["email"]] + docente = Docente.find_by(usuario: usuario) + turma = Turma.find_by(id: members["turma_id"]) + + turma&.update!(docente: docente) if docente + end end # registro de erros rescue StandardError => e @@ -118,4 +132,4 @@ def self.import!(upload_file) true end end -end \ No newline at end of file +end diff --git a/app/views/dashboards/admin.html.erb b/app/views/dashboards/admin.html.erb index 0a5cd4512e..5ee621dadc 100644 --- a/app/views/dashboards/admin.html.erb +++ b/app/views/dashboards/admin.html.erb @@ -8,7 +8,6 @@ Seus testes de criação de downloads entrarão aqui From 26d89775e8193567a488897ce05d221bf3ce65f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C3=A0=20Mattos?= Date: Sun, 28 Jun 2026 11:30:52 -0300 Subject: [PATCH 2/3] style: aplica correcoes do rubocop --- Gemfile | 1 - .../envio_formularios_controller.rb | 2 +- app/mailers/user_mailer.rb | 5 ++--- app/models/turma.rb | 1 - config/environments/development.rb | 2 +- config/initializers/assets.rb | 2 +- config/routes.rb | 2 +- db/migrate/20260611000003_create_turmas.rb | 2 +- .../cadastrar_usuarios_steps.rb | 22 +++++++++---------- spec/mailers/previews/user_mailer_preview.rb | 2 -- spec/mailers/user_mailer_spec.rb | 5 ++--- spec/system/cadastrar_usuarios_spec.rb | 16 +++++--------- 12 files changed, 25 insertions(+), 37 deletions(-) diff --git a/Gemfile b/Gemfile index 27ca1f7330..713f753211 100644 --- a/Gemfile +++ b/Gemfile @@ -74,4 +74,3 @@ group :test do end gem "activerecord-import" - diff --git a/app/controllers/envio_formularios_controller.rb b/app/controllers/envio_formularios_controller.rb index 4f321608e4..46da2dc476 100644 --- a/app/controllers/envio_formularios_controller.rb +++ b/app/controllers/envio_formularios_controller.rb @@ -36,7 +36,7 @@ def set_formulario def mensagem_erro_validacao(questoes, respostas_params) return "Todos os campos obrigatórios devem ser preenchidos" if campos_vazios?(questoes, respostas_params) - return "Por favor, insira um valor válido entre 1 e 5" if valores_invalidos?(questoes, respostas_params) + "Por favor, insira um valor válido entre 1 e 5" if valores_invalidos?(questoes, respostas_params) end def campos_vazios?(questoes, respostas_params) diff --git a/app/mailers/user_mailer.rb b/app/mailers/user_mailer.rb index 91b44e54e3..2f9a9c5eb8 100644 --- a/app/mailers/user_mailer.rb +++ b/app/mailers/user_mailer.rb @@ -1,13 +1,12 @@ class UserMailer < ApplicationMailer - def primeiro_acesso(usuario) @usuario = usuario - + @url_definir_senha = definir_senha_url(email: @usuario.email) mail( to: @usuario.email, - subject: 'Bem-vindo ao CAMAAR! Defina sua senha de acesso' + subject: "Bem-vindo ao CAMAAR! Defina sua senha de acesso" ) end end diff --git a/app/models/turma.rb b/app/models/turma.rb index d58f283190..cabbfdad79 100644 --- a/app/models/turma.rb +++ b/app/models/turma.rb @@ -7,4 +7,3 @@ class Turma < ApplicationRecord validates :codigo, presence: true validates :nome, presence: true end - diff --git a/config/environments/development.rb b/config/environments/development.rb index e01f1b671a..022b465892 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -42,7 +42,7 @@ config.action_mailer.perform_caching = false # adicionada config.action_mailer.delivery_method = :smtp - config.action_mailer.smtp_settings = { address: 'localhost', port: 1025 } + config.action_mailer.smtp_settings = { address: "localhost", port: 1025 } config.action_mailer.raise_delivery_errors = false diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb index 68eced570b..487324424f 100644 --- a/config/initializers/assets.rb +++ b/config/initializers/assets.rb @@ -4,4 +4,4 @@ Rails.application.config.assets.version = "1.0" # Add additional assets to the asset load path. -# Rails.application.config.assets.paths << Emoji.images_path \ No newline at end of file +# Rails.application.config.assets.paths << Emoji.images_path diff --git a/config/routes.rb b/config/routes.rb index 67093b87f5..47835419e9 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -10,7 +10,7 @@ get "/admin", to: "dashboards#admin", as: :admin_dashboard get "/discente", to: "dashboards#discente", as: :discente_dashboard - resources :turmas, only: [:index, :show] + resources :turmas, only: [ :index, :show ] get "/avaliacao", to: "dashboards#admin_avaliacao", as: :admin_avaliacao_dashboard get "/gerenciamento", to: "dashboards#admin_gerenciamento", as: :admin_gerenciamento_dashboard diff --git a/db/migrate/20260611000003_create_turmas.rb b/db/migrate/20260611000003_create_turmas.rb index 324a402ce8..cb65667751 100644 --- a/db/migrate/20260611000003_create_turmas.rb +++ b/db/migrate/20260611000003_create_turmas.rb @@ -4,7 +4,7 @@ def change t.references :departamento, null: false, foreign_key: true t.string :codigo, null: false t.string :nome, null: false - + t.string :turma t.string :semestre diff --git a/features/step_definitions/cadastrar_usuarios_steps.rb b/features/step_definitions/cadastrar_usuarios_steps.rb index b6332a46aa..130bb38b2d 100644 --- a/features/step_definitions/cadastrar_usuarios_steps.rb +++ b/features/step_definitions/cadastrar_usuarios_steps.rb @@ -36,7 +36,7 @@ Quando('eu clico em {string}') do |string| @import_usuarios = 'Importar Dados' expect(page).to have_content(@import_usuarios) # mudar para have_link ou have_button dependendo do tipo de elemento - + find('label', text: @import_usuarios).click end @@ -45,14 +45,13 @@ @arquivo_json = Rails.root.join('class_members.json') attach_file('arquivo_json', @arquivo_json, visible: :any) - + click_button('botao_enviar_oculto', visible: false) - #div_arquivo = find('#secao_importa').trigger('submit') - #expect(page).to have_content(@import_usuarios) # mudar para have_link ou have_button dependendo do tipo de elemento - - #find('label', text: @import_usuarios).click + # div_arquivo = find('#secao_importa').trigger('submit') + # expect(page).to have_content(@import_usuarios) # mudar para have_link ou have_button dependendo do tipo de elemento + # find('label', text: @import_usuarios).click end @@ -105,7 +104,6 @@ Então('o usuário não deve ter acesso ao sistema até que a senha seja definida') do expect(@discente_user.reload.primeiro_acesso).to be(true) - end @@ -115,7 +113,7 @@ @discente_user.update!(primeiro_acesso: false, password: "1234567", password_confirmation: "1234567") end -Então('o sistema deve atualizar o status do usuário para {string}') do +Então('o sistema deve atualizar o status do usuário para {string}') do expect(@discente_user.primeiro_acesso).to be(false) end @@ -138,16 +136,16 @@ Quando('seleciono um arquivo JSON contendo os dados de novos usuários') do expect(page).to have_link(@opcao_menu) # mudar para have_link ou have_button dependendo do tipo de elemento click_link @opcao_menu - + @import_usuarios = 'Importar Dados' expect(page).to have_content(@import_usuarios) # mudar para have_link ou have_button dependendo do tipo de elemento - + find('label', text: @import_usuarios).click @arquivo_json = Rails.root.join('class_members.json') attach_file('arquivo_json', @arquivo_json, visible: :any) - + click_button('botao_enviar_oculto', visible: false) end @@ -177,4 +175,4 @@ Então('o sistema não deve criar solicitações de definição de senha para os usuários duplicados') do expect(page).to have_current_path('/admin') -end \ No newline at end of file +end diff --git a/spec/mailers/previews/user_mailer_preview.rb b/spec/mailers/previews/user_mailer_preview.rb index 3e64a10b77..7208339ce8 100644 --- a/spec/mailers/previews/user_mailer_preview.rb +++ b/spec/mailers/previews/user_mailer_preview.rb @@ -1,9 +1,7 @@ # Preview all emails at http://localhost:3000/rails/mailers/user_mailer_mailer class UserMailerPreview < ActionMailer::Preview - # Preview this email at http://localhost:3000/rails/mailers/user_mailer_mailer/primeiro_acesso def primeiro_acesso UserMailer.primeiro_acesso end - end diff --git a/spec/mailers/user_mailer_spec.rb b/spec/mailers/user_mailer_spec.rb index e5cf9fc9f3..f16f00d2ba 100644 --- a/spec/mailers/user_mailer_spec.rb +++ b/spec/mailers/user_mailer_spec.rb @@ -6,13 +6,12 @@ it "renders the headers" do expect(mail.subject).to eq("Primeiro acesso") - expect(mail.to).to eq(["to@example.org"]) - expect(mail.from).to eq(["from@example.com"]) + expect(mail.to).to eq([ "to@example.org" ]) + expect(mail.from).to eq([ "from@example.com" ]) end it "renders the body" do expect(mail.body.encoded).to match("Hi") end end - end diff --git a/spec/system/cadastrar_usuarios_spec.rb b/spec/system/cadastrar_usuarios_spec.rb index b672f4e9ea..4fe812eaa8 100644 --- a/spec/system/cadastrar_usuarios_spec.rb +++ b/spec/system/cadastrar_usuarios_spec.rb @@ -59,9 +59,8 @@ @import_usuarios = 'Importar Dados' expect(page).to have_content(@import_usuarios) # mudar para have_link ou have_button dependendo do tipo de elemento - - find('label', text: @import_usuarios).click + find('label', text: @import_usuarios).click end it "Importar e selecionar o arquivo json" do @@ -77,19 +76,17 @@ @import_usuarios = 'Importar Dados' expect(page).to have_content(@import_usuarios) # mudar para have_link ou have_button dependendo do tipo de elemento - + find('label', text: @import_usuarios).click @arquivo_json = Rails.root.join('class_members.json') attach_file('arquivo_json', @arquivo_json, visible: :any) - - click_button('botao_enviar_oculto', visible: false) - #div_arquivo = find('#secao_importa').trigger('submit') - #expect(page).to_not have_content('Nenhuma turma cadastrada.') - + click_button('botao_enviar_oculto', visible: false) + # div_arquivo = find('#secao_importa').trigger('submit') + # expect(page).to_not have_content('Nenhuma turma cadastrada.') end it "Dados validos de importação" do @@ -104,7 +101,7 @@ click_link 'Gerenciamento' @import_usuarios = 'Importar Dados' - + find('label', text: @import_usuarios).click @arquivo_json = Rails.root.join('class_members.json') @@ -117,5 +114,4 @@ expect(Discente.count).to be > 0 expect(Docente.count).to be > 0 end - end From b3223922d858b6dbbdcceb4c14a6110980e62dd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?An=C3=A0=20Mattos?= Date: Sun, 28 Jun 2026 11:53:30 -0300 Subject: [PATCH 3/3] atualiza dependencias vulneraveis --- Gemfile.lock | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 73f39eef71..9dbb729cc5 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -112,7 +112,7 @@ GEM descendants_tracker (~> 0.0.1) concurrent-ruby (1.3.7) connection_pool (3.0.2) - crass (1.0.6) + crass (1.0.7) cucumber (10.2.0) base64 (~> 0.2) builder (~> 3.2) @@ -291,19 +291,19 @@ GEM net-protocol net-ssh (7.3.2) nio4r (2.7.5) - nokogiri (1.19.3-aarch64-linux-gnu) + nokogiri (1.19.4-aarch64-linux-gnu) racc (~> 1.4) - nokogiri (1.19.3-aarch64-linux-musl) + nokogiri (1.19.4-aarch64-linux-musl) racc (~> 1.4) - nokogiri (1.19.3-arm-linux-gnu) + nokogiri (1.19.4-arm-linux-gnu) racc (~> 1.4) - nokogiri (1.19.3-arm-linux-musl) + nokogiri (1.19.4-arm-linux-musl) racc (~> 1.4) - nokogiri (1.19.3-arm64-darwin) + nokogiri (1.19.4-arm64-darwin) racc (~> 1.4) - nokogiri (1.19.3-x86_64-linux-gnu) + nokogiri (1.19.4-x86_64-linux-gnu) racc (~> 1.4) - nokogiri (1.19.3-x86_64-linux-musl) + nokogiri (1.19.4-x86_64-linux-musl) racc (~> 1.4) ostruct (0.6.3) parallel (2.1.0) @@ -618,7 +618,7 @@ CHECKSUMS coercible (1.0.0) sha256=5081ad24352cc8435ce5472bc2faa30260c7ea7f2102cc6a9f167c4d9bffaadc concurrent-ruby (1.3.7) sha256=4412caec3a5ea2e5fdc52076724c071a81f2c0593d83b2ac8cbb8ca63b3151b0 connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a - crass (1.0.6) sha256=dc516022a56e7b3b156099abc81b6d2b08ea1ed12676ac7a5657617f012bd45d + crass (1.0.7) sha256=94868719948664c89ddcaf0a37c65048413dfcb1c869470a5f7a7ceb5390b295 cucumber (10.2.0) sha256=fdedbd31ecf40858b60f04853f2aa15c44f5c30bbac29c6a227fa1e7005a8158 cucumber-ci-environment (11.0.0) sha256=0df79a9e1d0b015b3d9def680f989200d96fef206f4d19ccf86a338c4f71d1e2 cucumber-core (16.2.0) sha256=592b58a95cf42feef8e5a349f68e363784ba3b6568ffbcf6776e38e136cf970b @@ -693,13 +693,13 @@ CHECKSUMS net-smtp (0.5.1) sha256=ed96a0af63c524fceb4b29b0d352195c30d82dd916a42f03c62a3a70e5b70736 net-ssh (7.3.2) sha256=65029e213c380e20e5fd92ece663934ab0a0fe888e0cd7cc6a5b664074362dd4 nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1 - nokogiri (1.19.3-aarch64-linux-gnu) sha256=46b89e5d7b9e844c2ee360794240c6ea2a4e6fa0c5892a4ed487db621224b639 - nokogiri (1.19.3-aarch64-linux-musl) sha256=8392dfdcd21be7a94dbbe9ccc138dea01b97b24cb2dc02a114ca98bfb1d9a0b7 - nokogiri (1.19.3-arm-linux-gnu) sha256=3919d5ffc334ad778a4a9eb88fda7dcb8b1fb58c8a52ac640c6dcd2f038e774f - nokogiri (1.19.3-arm-linux-musl) sha256=9ce1cb6346bb9c67b1550eb537aa183ead91e4b6eadb2f36ade02d8dd2a79fb6 - nokogiri (1.19.3-arm64-darwin) sha256=71b9bd424b1b7abc18b05052a1a3cfd3627abdca62be280854cc411791357e42 - nokogiri (1.19.3-x86_64-linux-gnu) sha256=2f5078620fe12e83669b5b17311b32532a8153d02eee7ad06948b926d6080976 - nokogiri (1.19.3-x86_64-linux-musl) sha256=248c906d2166eca5efb56d52fdee5f9a1f51d69a72e2b64fdac647b4ce39ea3f + nokogiri (1.19.4-aarch64-linux-gnu) sha256=1269fb644a6de405057a53dd5c762b1209b43ca7424f839454d3dbc677c31a8f + nokogiri (1.19.4-aarch64-linux-musl) sha256=35c65b9ce72b3bb03207bdbe7067915019dc18c1b9b59139684bd6690fdd01af + nokogiri (1.19.4-arm-linux-gnu) sha256=a301313e38bb065d68239e79734bcd6f56fb6efaacebde29e9abf2a4735340ca + nokogiri (1.19.4-arm-linux-musl) sha256=588923c101bcfa78869734d247d25b598674323e7f22474fc468f6e5647311eb + nokogiri (1.19.4-arm64-darwin) sha256=a46db9853286e6597b36ebc6953817d15acf3a299583eb3f89fdc6f91dd63527 + nokogiri (1.19.4-x86_64-linux-gnu) sha256=379fae440b28915e3f19d752ce2dcf8465ed2b2fbefd2a7ca0dd497bc981a06a + nokogiri (1.19.4-x86_64-linux-musl) sha256=17dfb7c1fa194ae02fbf7c51a7afc8d278045ab3fdacfd86f91d02d7b274470b ostruct (0.6.3) sha256=95a2ed4a4bd1d190784e666b47b2d3f078e4a9efda2fccf18f84ddc6538ed912 parallel (2.1.0) sha256=b35258865c2e31134c5ecb708beaaf6772adf9d5efae28e93e99260877b09356 parser (3.3.11.1) sha256=d17ace7aabe3e72c3cc94043714be27cc6f852f104d81aa284c2281aecc65d54