enviar notificaciones!
This commit is contained in:
parent
532054de11
commit
b1de74aafe
14 changed files with 149 additions and 144 deletions
18
.rubocop.yml
18
.rubocop.yml
|
@ -1,22 +1,6 @@
|
|||
inherit_from: .rubocop_todo.yml
|
||||
#inherit_from: .rubocop_todo.yml
|
||||
|
||||
# No siempre queremos metadatear los modelos
|
||||
Rails/CreateTableWithTimestamps:
|
||||
Enabled: false
|
||||
# Queremos poder hacer comentarios en castellano, esto quiere que
|
||||
# saquemos las tildes
|
||||
Style/AsciiComments:
|
||||
Enabled: false
|
||||
# El estilo de módulo y clases anidados agrega mucha indentación para
|
||||
# nuestros gusto
|
||||
Style/ClassAndModuleChildren:
|
||||
Enabled: false
|
||||
Metrics/LineLength:
|
||||
Exclude:
|
||||
- 'db/schema.rb'
|
||||
Metrics/BlockLength:
|
||||
Exclude:
|
||||
- 'db/schema.rb'
|
||||
- 'config/routes.rb'
|
||||
- 'db/seeds.rb'
|
||||
- 'config/environments/production.rb'
|
||||
|
|
|
@ -1,80 +0,0 @@
|
|||
# This configuration was generated by
|
||||
# `rubocop --auto-gen-config`
|
||||
# on 2019-04-05 17:51:53 -0300 using RuboCop version 0.66.0.
|
||||
# The point is for the user to remove these configuration records
|
||||
# one by one as the offenses are removed from the code base.
|
||||
# Note that changes in the inspected code, or installation of new
|
||||
# versions of RuboCop, may require this file to be generated again.
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: empty_lines, no_empty_lines
|
||||
Layout/EmptyLinesAroundBlockBody:
|
||||
Exclude:
|
||||
- 'db/schema.rb'
|
||||
|
||||
# Offense count: 1
|
||||
Metrics/AbcSize:
|
||||
Max: 18
|
||||
|
||||
# Offense count: 1
|
||||
Metrics/CyclomaticComplexity:
|
||||
Max: 9
|
||||
|
||||
# Offense count: 2
|
||||
# Configuration parameters: CountComments, ExcludedMethods.
|
||||
Metrics/MethodLength:
|
||||
Max: 13
|
||||
|
||||
# Offense count: 1
|
||||
Metrics/PerceivedComplexity:
|
||||
Max: 9
|
||||
|
||||
# Offense count: 1
|
||||
Style/Documentation:
|
||||
Exclude:
|
||||
- 'spec/**/*'
|
||||
- 'test/**/*'
|
||||
- 'config/application.rb'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle.
|
||||
# SupportedStyles: when_needed, always, never
|
||||
Style/FrozenStringLiteralComment:
|
||||
Exclude:
|
||||
- 'db/schema.rb'
|
||||
|
||||
# Offense count: 2
|
||||
# Cop supports --auto-correct.
|
||||
Style/IfUnlessModifier:
|
||||
Exclude:
|
||||
- 'bin/bundle'
|
||||
|
||||
# Offense count: 2
|
||||
Style/MixinUsage:
|
||||
Exclude:
|
||||
- 'bin/setup'
|
||||
- 'bin/update'
|
||||
|
||||
# Offense count: 1
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: MinDigits, Strict.
|
||||
Style/NumericLiterals:
|
||||
Exclude:
|
||||
- 'db/schema.rb'
|
||||
|
||||
# Offense count: 4
|
||||
# Cop supports --auto-correct.
|
||||
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
|
||||
# SupportedStyles: single_quotes, double_quotes
|
||||
Style/StringLiterals:
|
||||
Exclude:
|
||||
- 'db/schema.rb'
|
||||
|
||||
# Offense count: 12
|
||||
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
||||
# URISchemes: http, https
|
||||
Metrics/LineLength:
|
||||
Max: 190
|
2
Gemfile
2
Gemfile
|
@ -40,7 +40,7 @@ group :development do
|
|||
gem 'listen', '>= 3.0.5', '< 3.2'
|
||||
# Spring speeds up development by keeping your application running in
|
||||
# the background. Read more: https://github.com/rails/spring
|
||||
gem 'rubocop'
|
||||
gem 'rubocop-rails'
|
||||
gem 'spring'
|
||||
gem 'spring-watcher-listen', '~> 2.0.0'
|
||||
gem 'yard'
|
||||
|
|
23
Gemfile.lock
23
Gemfile.lock
|
@ -64,7 +64,7 @@ GEM
|
|||
hkdf (0.3.0)
|
||||
i18n (1.6.0)
|
||||
concurrent-ruby (~> 1.0)
|
||||
jaro_winkler (1.5.2)
|
||||
jaro_winkler (1.5.3)
|
||||
jbuilder (2.8.0)
|
||||
activesupport (>= 4.2.0)
|
||||
multi_json (>= 1.2)
|
||||
|
@ -90,13 +90,12 @@ GEM
|
|||
nio4r (2.3.1)
|
||||
nokogiri (1.10.3)
|
||||
mini_portile2 (~> 2.4.0)
|
||||
parallel (1.16.2)
|
||||
parser (2.6.2.0)
|
||||
parallel (1.17.0)
|
||||
parser (2.6.3.0)
|
||||
ast (~> 2.4.0)
|
||||
pry (0.12.2)
|
||||
coderay (~> 1.1.0)
|
||||
method_source (~> 0.9.0)
|
||||
psych (3.1.0)
|
||||
public_suffix (4.0.0)
|
||||
puma (3.12.1)
|
||||
rack (2.0.7)
|
||||
|
@ -132,15 +131,17 @@ GEM
|
|||
rb-fsevent (0.10.3)
|
||||
rb-inotify (0.10.0)
|
||||
ffi (~> 1.0)
|
||||
rubocop (0.66.0)
|
||||
rubocop (0.72.0)
|
||||
jaro_winkler (~> 1.5.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.5, != 2.5.1.1)
|
||||
psych (>= 3.1.0)
|
||||
parser (>= 2.6)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 1.6)
|
||||
ruby-progressbar (1.10.0)
|
||||
unicode-display_width (>= 1.4.0, < 1.7)
|
||||
rubocop-rails (2.2.0)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 0.72.0)
|
||||
ruby-progressbar (1.10.1)
|
||||
ruby_dep (1.5.0)
|
||||
spring (2.0.2)
|
||||
activesupport (>= 4.2)
|
||||
|
@ -159,7 +160,7 @@ GEM
|
|||
thread_safe (0.3.6)
|
||||
tzinfo (1.2.5)
|
||||
thread_safe (~> 0.1)
|
||||
unicode-display_width (1.5.0)
|
||||
unicode-display_width (1.6.0)
|
||||
validate_url (1.0.8)
|
||||
activemodel (>= 3.0.0)
|
||||
public_suffix
|
||||
|
@ -185,7 +186,7 @@ DEPENDENCIES
|
|||
puma (~> 3.11)
|
||||
rack-cors
|
||||
rails (~> 5.2.3)
|
||||
rubocop
|
||||
rubocop-rails
|
||||
spring
|
||||
spring-watcher-listen (~> 2.0.0)
|
||||
sqlite3
|
||||
|
|
|
@ -47,6 +47,9 @@ class BarcasController < ApplicationController
|
|||
@barca.piratas << current_pirata
|
||||
|
||||
if @barca.save
|
||||
piratas = Pirata.todas_menos(current_pirata).pluck(:id)
|
||||
notify(subject: 'barcas.create.subject', piratas: piratas)
|
||||
|
||||
render status: :created
|
||||
else
|
||||
render json: { errors: @barca.errors.messages },
|
||||
|
@ -129,4 +132,17 @@ class BarcasController < ApplicationController
|
|||
def find_barca
|
||||
@barca = Barca.find(params[:barca_id])
|
||||
end
|
||||
|
||||
def notify(piratas:, subject:)
|
||||
# Notificar a todas las piratas que hay una nueva barca para que
|
||||
# se puedan sumar
|
||||
payload = WebpushPayload.new(subject: I18n.t(subject,
|
||||
barca: @barca.nombre),
|
||||
message: @barca.descripcion,
|
||||
endpoint: barca_path(@barca))
|
||||
|
||||
WebpushJob.perform_later(piratas: piratas,
|
||||
ttl: 7.days.to_i,
|
||||
payload: payload.to_json)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -66,8 +66,7 @@ class ConsensosController < ApplicationController
|
|||
begin
|
||||
@consenso = @barca.consensos.find(params[:id])
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
render json: {}, status: :not_found
|
||||
return
|
||||
render(json: {}, status: :not_found) && return
|
||||
end
|
||||
|
||||
if @consenso.posiciones.empty? && @consenso.destroy
|
||||
|
|
|
@ -15,7 +15,8 @@ class PosicionesController < ApplicationController
|
|||
# Crea una posición dentro de un consenso
|
||||
#
|
||||
# @param :consenso_id [Integer] El ID del consenso
|
||||
# @param :posicion [Hash] { posicion: { estado: @string, comentario: @string } }
|
||||
# @param :posicion [Hash] { posicion: { estado: @string,
|
||||
# comentario: @string } }
|
||||
# @return [Hash] { id: @int, estado: @string, comentario: @string,
|
||||
# pirata: @pirata }
|
||||
def create
|
||||
|
|
37
app/jobs/webpush_job.rb
Normal file
37
app/jobs/webpush_job.rb
Normal file
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Envía las notificaciones
|
||||
class WebpushJob < ApplicationJob
|
||||
queue_as :default
|
||||
|
||||
# @param :piratas [String,Array] 'all' para traer todas, array de IDs
|
||||
# para filtrar
|
||||
# @param :payload [WebpushPayload] La notificación a enviar
|
||||
# @param :urgency [Symbol] La urgencia
|
||||
# @param :ttl [Any] Duración convertible a segundos
|
||||
def perform(piratas:, payload:, urgency: :normal, ttl: 1.day.to_i)
|
||||
# Encontrar todas las piratas
|
||||
piratas = find_piratas(piratas)
|
||||
payload = WebpushPayload.from_json payload
|
||||
|
||||
# No cargar todas las piratas en memoria!
|
||||
piratas.find_each do |pirata|
|
||||
# Enviarles a todas sus suscripciones
|
||||
pirata.webpush_subscriptions.find_each do |subscription|
|
||||
subscription.payload_send(payload: payload,
|
||||
urgency: urgency,
|
||||
ttl: ttl)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_piratas(ids)
|
||||
if ids == 'all'
|
||||
Pirata.all
|
||||
else
|
||||
Pirata.where(id: ids)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -18,4 +18,6 @@ class Pirata < ApplicationRecord
|
|||
# Una por correo
|
||||
validates :email, presence: true, uniqueness: true
|
||||
validates :nick, presence: true, uniqueness: true
|
||||
|
||||
scope :todas_menos, ->(pirata) { where.not(id: pirata) }
|
||||
end
|
||||
|
|
20
app/models/webpush_payload.rb
Normal file
20
app/models/webpush_payload.rb
Normal file
|
@ -0,0 +1,20 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# El payload que se envía en la notificación
|
||||
#
|
||||
# @param :subject [String] El título de la notificación
|
||||
# @param :message [String] El cuerpo de la notificación
|
||||
# @param :endpoint [String] La URL a visitar al abrir la notificación
|
||||
WebpushPayload = Struct.new(:subject, :message, :endpoint,
|
||||
keyword_init: true) do
|
||||
# Convertir el payload a JSON para poder enviarlo
|
||||
#
|
||||
# @return String
|
||||
def to_json(opts = nil)
|
||||
to_h.to_json(opts)
|
||||
end
|
||||
|
||||
def self.from_json(string)
|
||||
new(JSON.parse(string))
|
||||
end
|
||||
end
|
|
@ -6,4 +6,30 @@ class WebpushSubscription < ApplicationRecord
|
|||
validates :endpoint, url: true
|
||||
validates_uniqueness_of :auth, scope: %i[p256dh endpoint],
|
||||
case_sensitive: false
|
||||
|
||||
URGENCY = %w[very-low low normal high].freeze
|
||||
|
||||
# Envía la notificación
|
||||
def payload_send(payload:, urgency: :normal, ttl: 1.day)
|
||||
Webpush.payload_send(
|
||||
vapid: {
|
||||
subject: 'mailto:lumi@partidopirata.com.ar',
|
||||
public_key: Rails.application.credentials.vapid.public_key,
|
||||
private_key: Rails.application.credentials.vapid.private_key
|
||||
},
|
||||
endpoint: endpoint, auth: auth, p256dh: p256dh,
|
||||
ttl: ttl.to_i, urgency: normalize_urgency(urgency),
|
||||
message: payload.to_json
|
||||
)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def normalize_urgency(urgency)
|
||||
if URGENCY.includes? urgency.to_s
|
||||
urgency.to_s
|
||||
else
|
||||
'normal'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,33 +1,4 @@
|
|||
# Files in the config/locales directory are used for internationalization
|
||||
# and are automatically loaded by Rails. If you want to use locales other
|
||||
# than English, add the necessary files in this directory.
|
||||
#
|
||||
# To use the locales, use `I18n.t`:
|
||||
#
|
||||
# I18n.t 'hello'
|
||||
#
|
||||
# In views, this is aliased to just `t`:
|
||||
#
|
||||
# <%= t('hello') %>
|
||||
#
|
||||
# To use a different locale, set it with `I18n.locale`:
|
||||
#
|
||||
# I18n.locale = :es
|
||||
#
|
||||
# This would use the information in config/locales/es.yml.
|
||||
#
|
||||
# The following keys must be escaped otherwise they will not be retrieved by
|
||||
# the default I18n backend:
|
||||
#
|
||||
# true, false, on, off, yes, no
|
||||
#
|
||||
# Instead, surround them with single quotes.
|
||||
#
|
||||
# en:
|
||||
# 'true': 'foo'
|
||||
#
|
||||
# To learn more, please read the Rails Internationalization guide
|
||||
# available at http://guides.rubyonrails.org/i18n.html.
|
||||
|
||||
en:
|
||||
hello: "Hello world"
|
||||
barcas:
|
||||
create:
|
||||
subject: '%{barca} has been created!'
|
||||
|
|
4
config/locales/es.yml
Normal file
4
config/locales/es.yml
Normal file
|
@ -0,0 +1,4 @@
|
|||
es:
|
||||
barcas:
|
||||
create:
|
||||
subject: '%{barca} creada, ¡al abordaje!'
|
24
test/jobs/webpush_job_test.rb
Normal file
24
test/jobs/webpush_job_test.rb
Normal file
|
@ -0,0 +1,24 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'test_helper'
|
||||
|
||||
class WebpushJobTest < ActiveJob::TestCase
|
||||
test 'se pueden enviar a todas las piratas' do
|
||||
payload = WebpushPayload.new(subject: 'test', message: 'test', endpoint: 'https://partidopirata.com.ar')
|
||||
|
||||
assert_nothing_raised do
|
||||
WebpushJob.perform_now(piratas: 'all', payload: payload.to_json,
|
||||
urgency: :low, ttl: 1.day.to_i)
|
||||
end
|
||||
end
|
||||
|
||||
test 'se pueden enviar a algunas piratas' do
|
||||
pirata = create :pirata
|
||||
payload = WebpushPayload.new(subject: 'test', message: 'test', endpoint: 'https://partidopirata.com.ar')
|
||||
|
||||
assert_nothing_raised do
|
||||
WebpushJob.perform_now(piratas: [pirata.id], payload: payload.to_json,
|
||||
urgency: :low, ttl: 1.day.to_i)
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue