diff --git a/Gemfile b/Gemfile index 82ee274f..fcf9302f 100644 --- a/Gemfile +++ b/Gemfile @@ -2,6 +2,8 @@ source 'https://rubygems.org' # The central piece of this application: the month calendar view gem 'simple_calendar' +# The recurrence management library +gem 'ice_cube' gem 'rails' gem 'has_scope' diff --git a/Gemfile.lock b/Gemfile.lock index 7fb7371b..57749406 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -210,6 +210,7 @@ GEM http_accept_language (2.0.5) http_parser.rb (0.6.0) i18n (0.7.0) + ice_cube (0.14.0) inherited_resources (1.6.0) actionpack (>= 3.2, < 5) has_scope (~> 0.6.0.rc) @@ -445,6 +446,7 @@ DEPENDENCIES has_scope http_accept_language i18n-active_record! + ice_cube jbuilder jquery-rails (< 4.1) jquery-sparkline-rails! diff --git a/app/assets/javascripts/events.js.coffee b/app/assets/javascripts/events.js.coffee index 0eec6a1f..b349d204 100644 --- a/app/assets/javascripts/events.js.coffee +++ b/app/assets/javascripts/events.js.coffee @@ -1,4 +1,14 @@ $(document).on 'turbolinks:load', -> + # Quick mechanism so that the ice cube rule only appears when useful + if $('#event_repeat').val() == '0' + $('.field.rule').hide() + + $('#event_repeat').change -> + if $(this).val() > 0 + $('.field.rule').show() + else + $('.field.rule').hide() + # Manage event tags edition $('#event_tags').each -> elt = $(this) diff --git a/app/assets/stylesheets/form.sass b/app/assets/stylesheets/form.sass index a4214396..e767dc29 100644 --- a/app/assets/stylesheets/form.sass +++ b/app/assets/stylesheets/form.sass @@ -52,6 +52,10 @@ content: $fa-var-toggle-on .field.end_time label:before content: $fa-var-toggle-off + .field.repeat label:before + content: $fa-var-repeat + .field.rule > label:before + content: $fa-var-calculator .field.description label:before content: $fa-var-pencil-square-o .field.place_name label:before diff --git a/app/controllers/events_controller.rb b/app/controllers/events_controller.rb index 7a022609..4044c7c5 100644 --- a/app/controllers/events_controller.rb +++ b/app/controllers/events_controller.rb @@ -102,9 +102,9 @@ class EventsController < ApplicationController # through def event_params params.require(:event) - .permit :lock_version, :title, :start_time, :end_time, :description, - :place_name, :address, :city, :region_id, :locality, :url, - :contact, :submitter, :tags + .permit :lock_version, :title, :start_time, :end_time, :repeat, :rule, + :description, :place_name, :address, :city, :region_id, + :locality, :url, :contact, :submitter, :tags end def locked diff --git a/app/controllers/moderations_controller.rb b/app/controllers/moderations_controller.rb index c2b2a26c..b9db7f6a 100644 --- a/app/controllers/moderations_controller.rb +++ b/app/controllers/moderations_controller.rb @@ -65,9 +65,9 @@ class ModerationsController < ApplicationController # through. def moderation_params params.require(:event) - .permit :lock_version, :title, :start_time, :end_time, :description, - :place_name, :address, :city, :region_id, :locality, :url, - :contact, :submitter, :tags + .permit :lock_version, :title, :start_time, :end_time, :repeat, :rule, + :description, :place_name, :address, :city, :region_id, + :locality, :url, :contact, :submitter, :tags end # Useful to manage absolute url in mails diff --git a/app/models/event.rb b/app/models/event.rb index 62548799..314fd838 100644 --- a/app/models/event.rb +++ b/app/models/event.rb @@ -2,14 +2,20 @@ class Event < ActiveRecord::Base extend SimpleCalendar strip_attributes - has_paper_trail ignore: [:last_updated, :secret, :submitter, :decision_time, - :lock_version, :latitude, :longitude] + has_paper_trail ignore: [:last_updated, :lock_version, :secret, + :submitter, :decision_time, + :latitude, :longitude] belongs_to :region + # This is the scheduled first event + belongs_to :event has_many :notes, dependent: :destroy + has_many :events, dependent: :destroy validates :title, presence: true validate :end_after_start + RULES = %w(daily weekly monthly).freeze + validates :rule, inclusion: RULES validates :description, presence: true validates :city, presence: true validates :region, presence: true @@ -25,8 +31,14 @@ class Event < ActiveRecord::Base # Mechanism to store some reason which can be used when sending notifications attr_accessor :reason + before_validation EventCallbacks + + before_create EventCallbacks after_create EventCallbacks + + before_update EventCallbacks after_update EventCallbacks + after_destroy EventCallbacks scope :moderated, ->(*) { where moderated: true } @@ -55,11 +67,6 @@ class Event < ActiveRecord::Base scope :tag, ->(tag) { where 'tags like ?', "%#{tag}%" } scope :geo, -> { where 'latitude is not null and longitude is not null' } - before_validation do - # Tags are always downcased - self.tags = tags.mb_chars.downcase if tags - end - before_validation on: :create do self.submission_time = Time.zone.now self.decision_time = Time.zone.now @@ -73,22 +80,11 @@ class Event < ActiveRecord::Base self.longitude = nil if address_changed? end - before_create do - self.secret = SecureRandom.urlsafe_base64(32)[0...32] - self.moderator_mail_id = SecureRandom.urlsafe_base64(32)[0...32] - self.submitter_mail_id = SecureRandom.urlsafe_base64(32)[0...32] - end - - before_update do - self.decision_time = Time.zone.now if moderated? && moderated_changed? - end - def as_json(_options = {}) { type: 'Feature', properties: { id: id, name: title, start_time: start_time, end_time: end_time, place_name: place_name, address: address, city: city, locality: locality, - tags: tags, - popupContent: "#{self}" + tags: tags, popupContent: "#{self}" }, geometry: { type: 'Point', coordinates: [longitude, latitude] } } end @@ -98,6 +94,12 @@ class Event < ActiveRecord::Base [address, city].compact.join ', ' end + def schedule + IceCube::Schedule.new(start_time, end_time: end_time) do |s| + s.add_recurrence_rule IceCube::Rule.send(rule).count(repeat + 1) + end + end + def hashtags tags.split.map { |tag| "##{tag.tr('-', '_').camelize :lower}" } end diff --git a/app/models/event_callbacks.rb b/app/models/event_callbacks.rb index 045d9cd2..ea0d5e19 100644 --- a/app/models/event_callbacks.rb +++ b/app/models/event_callbacks.rb @@ -1,28 +1,66 @@ # All the mail and tweet related callbacks to event's lifecycle +# also the scheduled events class EventCallbacks + def self.before_validation(event) + # Tags are always downcased + event.tags = event.tags.mb_chars.downcase if event.tags + end + + def self.before_create(event) + event.secret = SecureRandom.urlsafe_base64(32)[0...32] + event.moderator_mail_id = SecureRandom.urlsafe_base64(32)[0...32] + event.submitter_mail_id = SecureRandom.urlsafe_base64(32)[0...32] + end + def self.after_create(event) EventMailer.create(event).deliver_now! ModerationMailer.create(event).deliver_now! end + def self.before_update(event) + if event.moderated_changed? && event.moderated? + event.decision_time = Time.zone.now + create_repeats event if event.repeat > 0 + end + end + def self.after_update(event) if event.moderated_changed? - tweet(event) + tweet event - # Send an acceptation mail to its author - EventMailer.accept(event).deliver_now + if ActionMailer::Base.default_url_options[:host] + # Send an acceptation mail to its author + EventMailer.accept(event).deliver_now - # Send an acceptation mail to moderators - ModerationMailer.accept(event).deliver_now - else + # Send an acceptation mail to moderators + ModerationMailer.accept(event).deliver_now + end + + elsif ActionMailer::Base.default_url_options[:host] # Send an update mail to moderators ModerationMailer.update(event).deliver_now end end def self.after_destroy(event) - EventMailer.destroy(event).deliver_now - ModerationMailer.destroy(event).deliver_now + if ActionMailer::Base.default_url_options[:host] + EventMailer.destroy(event).deliver_now + ModerationMailer.destroy(event).deliver_now + end + end + + # Create multiple events corresponding to a repetition + def self.create_repeats(event) + event.schedule.last(event.repeat).each do |schedule| + event.events.build create_sub_event(event, schedule) + end + end + + def self.create_sub_event(event, schedule) + att = event.attributes.reject { |a| a == 'id' || a == 'lock_version' } + att[:start_time] = schedule.start_time + att[:end_time] = schedule.end_time + att end # Tweet this event, if configured using apache/system variables! diff --git a/app/views/event_mailer/accept.text.haml b/app/views/event_mailer/accept.text.haml index 2728ddae..739561ab 100644 --- a/app/views/event_mailer/accept.text.haml +++ b/app/views/event_mailer/accept.text.haml @@ -7,6 +7,13 @@ = t '.delete_link' = cancel_event_url @event, secret: @event.secret \ +- if @event.repeat > 0 && !@event.event_id + = t '.repeat_helper', count: @event.repeat + - @event.events.each do |e| + = e + = edit_event_url e, secret: e.secret + = cancel_event_url e, secret: e.secret +\ = render file: '/events/show' \ = t '.signature' diff --git a/app/views/events/_event.haml b/app/views/events/_event.haml index 1f045a52..d4085b2e 100644 --- a/app/views/events/_event.haml +++ b/app/views/events/_event.haml @@ -6,3 +6,5 @@ = link_to event do %strong.city{ title: event.address }= event.city = event.title + - if event.repeat > 0 + %em.fa.fa-repeat(title="#{event.repeat} - #{t event.rule, scope: 'activerecord.attributes.event.rule_values'}") diff --git a/app/views/events/_form.html.haml b/app/views/events/_form.html.haml index e4d85edf..d21fc670 100644 --- a/app/views/events/_form.html.haml +++ b/app/views/events/_form.html.haml @@ -12,13 +12,30 @@ .field.title = f.label :title - = f.text_field :title, required: true, placeholder: "#{t '.title_helper'}" + = f.text_field :title, required: true, placeholder: t('.title_helper') .field.start_time = f.label :start_time = f.datetime_local_field :start_time, required: true .field.end_time = f.label :end_time = f.datetime_local_field :end_time, required: true + + - unless @event.moderated? + .field.repeat + = f.label :repeat + = f.number_field :repeat, in: 0..40, maxlength: 2, size: 2 + + .field.rule + .helper + :markdown + #{t '.rule_helper'} + = f.label :rule + %span.radios + - Event::RULES.each do |rule| + = f.radio_button :rule, rule + = f.label "rule_#{rule}", + t(rule, scope: 'activerecord.attributes.event.rule_values') + .field.description .helper :markdown @@ -46,7 +63,8 @@ %option= city .field.region = f.label :region - = f.collection_select :region_id, Region.all, :id, :name, { include_blank: true } + = f.collection_select :region_id, Region.all, :id, :name, + include_blank: true .field.locality = f.label :locality %span.radios diff --git a/app/views/events/show.html.haml b/app/views/events/show.html.haml index ff4bd1f5..d38dd006 100644 --- a/app/views/events/show.html.haml +++ b/app/views/events/show.html.haml @@ -77,8 +77,8 @@ "http://fr.wikipedia.org/wiki/#{url_encode @event.region.try :name}" - if @event.latitude && @event.longitude - .event#map{ data: { url: "#{maps_path format: :json}", - latitude: "#{@event.latitude}", longitude: "#{@event.longitude}" } } + .event#map{ data: { url: maps_path(format: :json), + latitude: @event.latitude, longitude: @event.longitude } } - elsif controller.action_name != 'show' %em.fa.fa-compress @@ -114,3 +114,13 @@ %span.label= Event.human_attribute_name :tags - @event.tags.split.each do |tag| = link_to tag, tag_path(tag), rel: :tag + +- if @event.repeat > 0 + %h3 + %em.fa.fa-repeat + = t @event.rule, scope: 'activerecord.attributes.event.rule_values' + + %ul + %li= link_to_unless_current @event.event || @event, @event.event || @event + - (@event.event || @event).events.each do |e| + %li= link_to_unless_current e, e diff --git a/app/views/events/show.text.haml b/app/views/events/show.text.haml index 69e06f47..6a1ffc3b 100644 --- a/app/views/events/show.text.haml +++ b/app/views/events/show.text.haml @@ -2,6 +2,9 @@ #{Event.human_attribute_name(:title).concat(':').ljust 12 } #{@event.title} #{Event.human_attribute_name(:start_time).concat(':').ljust 12 } #{l @event.start_time, format: :at} #{Event.human_attribute_name(:end_time).concat(':').ljust 12 } #{l @event.end_time, format: :at} +-if @event.repeat > 0 + #{Event.human_attribute_name(:repeat).concat(':').ljust 12 } #{@event.repeat} + #{Event.human_attribute_name(:rule).concat(':').ljust 12 } #{t @event.rule, scope: 'activerecord.attributes.event.rule_values'} #{Event.human_attribute_name(:place_name).concat(':').ljust 12 } #{@event.place_name} #{Event.human_attribute_name(:address).concat(':').ljust 12 } #{@event.address} #{Event.human_attribute_name(:city).concat(':').ljust 12 } #{@event.city} diff --git a/app/views/moderations/validate.html.haml b/app/views/moderations/validate.html.haml index 2cc230eb..7990bdc9 100644 --- a/app/views/moderations/validate.html.haml +++ b/app/views/moderations/validate.html.haml @@ -24,6 +24,18 @@ = @event.to_tweet +- if @event.repeat > 0 + %fieldset + %legend + %em.fa.fa-repeat + = Event.human_attribute_name :repeat + + %h3= t '.repeat_helper', count: @event.repeat + + %p.rule + = Event.human_attribute_name :rule + = t @event.rule, scope: 'activerecord.attributes.event.rule_values' + %fieldset %legend %em.fa.fa-calendar diff --git a/config/locales/ice_cube.fr.yml b/config/locales/ice_cube.fr.yml new file mode 100644 index 00000000..f616871d --- /dev/null +++ b/config/locales/ice_cube.fr.yml @@ -0,0 +1,173 @@ +fr: + ice_cube: + pieces_connector: ' / ' + not: 'pas %{target}' + not_on: 'pas durant %{target}' + date: + formats: + default: '%d %B %Y' + month_names: + - + - janvier + - février + - mars + - avril + - mai + - juin + - juillet + - août + - septembre + - octobre + - novembre + - décembre + day_names: + - dimanche + - lundi + - mardi + - mercredi + - jeudi + - vendredi + - samedi + times: + other: '%{count} fois' + one: '%{count} fois' + until: "jusqu'au %{date}" + days_of_week: '%{segments} %{day}' + days_of_month: + other: '%{segments} jours du mois' + one: '%{segments} jours du mois' + days_of_year: + other: "%{segments} jours de l'année" + one: "%{segments} jours de l'année" + at_hours_of_the_day: + other: aux %{segments} heures de la journée + one: à %{segments}h + on_minutes_of_hour: + other: aux %{segments} minutes de l'heure + one: à la %{segments} minute de l'heure + at_seconds_of_minute: + other: aux %{segments} secondes + one: à la %{segments} seconde + on_seconds_of_minute: + other: aux %{segments} secondes de la minute + one: à la %{segments} seconde de la minute + each_second: + one: Toutes les secondes + other: Toutes les %{count} secondes + each_minute: + one: Toutes les minutes + other: Toutes les %{count} minutes + each_hour: + one: Toutes les heures + other: Toutes les %{count} heures + each_day: + one: Quotidien + other: Tous les %{count} jours + each_week: + one: Hebdomadaire + other: Toutes les %{count} semaines + each_month: + one: Mensuel + other: Tous les %{count} mois + each_year: + one: Annuel + other: Tous les %{count} ans + 'on': les %{sentence} + in: 'en %{target}' + integer: + negative: '%{ordinal} depuis la fin' + literal_ordinals: + -1: derniers + -2: avant-derniers + ordinal: '%{number}%{ordinal}' + ordinals: + default: '°' + 1: ° + on_weekends: pendant les weekends + on_weekdays: pendant les jours ouvrés + days_on: + - dimanches + - lundis + - mardis + - mercredis + - jeudis + - vendredis + - samedis + on_days: les %{days} + array: + last_word_connector: ', et ' + two_words_connector: ' et ' + words_connector: ', ' + string: + format: + day: '%{rest} %{current}' + day_of_week: '%{rest} %{current}' + day_of_month: '%{rest} %{current}' + day_of_year: '%{rest} %{current}' + hour_of_day: '%{rest} %{current}' + minute_of_hour: '%{rest} %{current}' + until: '%{rest} %{current}' + count: '%{rest} %{current}' + default: '%{rest} %{current}' + + date: + abbr_day_names: + - Dim + - Lun + - Mar + - Mer + - Jeu + - Ven + - Sam + abbr_month_names: + - + - Jan + - Fév + - Mar + - Avr + - Mai + - Jun + - Jul + - Aou + - Sep + - Oct + - Nov + - Déc + day_names: + - dimanche + - lundi + - mardi + - mecredi + - jeudi + - vendredi + - samedi + formats: + default: "%d-%m-%Y" + long: "%d %B %Y" + short: "%d %b" + month_names: + - + - janvier + - février + - mars + - avril + - mai + - juin + - juillet + - août + - septembre + - octobre + - novembre + - décembre + order: + - :year + - :month + - :day + + time: + am: am + formats: + default: "%a, %d %b %Y %H:%M:%S %z" + long: "%d %B %Y %H:%M" + short: "%d %b %H:%M" + pm: pm \ No newline at end of file diff --git a/config/locales/models/en.yml b/config/locales/models/en.yml index 3ce86b71..64665a48 100644 --- a/config/locales/models/en.yml +++ b/config/locales/models/en.yml @@ -63,6 +63,13 @@ en: title: Title start_time: Start end_time: End + repeat: Repeat + rule: Règle + rule_values: + daily: Daily + weekly: Weekly + monthly: Monthly + yearly: Yearly description: Description place_name: Place name address: Address diff --git a/config/locales/models/fr.yml b/config/locales/models/fr.yml index 181f8298..27ad53e3 100644 --- a/config/locales/models/fr.yml +++ b/config/locales/models/fr.yml @@ -63,6 +63,13 @@ fr: title: Titre start_time: Début end_time: Fin + repeat: Répéter + rule: Règle + rule_values: + daily: Journalière + weekly: Hebdomadaire + monthly: Mensuelle + yearly: Annuelle description: Description place_name: Nom du lieu address: Adresse diff --git a/config/locales/views/en.yml b/config/locales/views/en.yml index dbc7b543..252f4070 100644 --- a/config/locales/views/en.yml +++ b/config/locales/views/en.yml @@ -89,6 +89,8 @@ it more readable or agreable. ok: Your event was updated form: title_helper: Less than 5 words, without address or date + rule_helper: Repeated events will be generated during validation. You + will receive by mail edition and cancellation links description_helper: Describe with as much precision as possible your event address_helper: Associated to the city and region, it will generate an [OpenStreetMap](http://www.openstreetmap.org) map, displayed alongside @@ -179,6 +181,10 @@ it more readable or agreable. ok: Yes ko: Moderation tweet_helper: A tweet will be published, here is its content + repeat_helper: + zero: + one: One other event will be generated + other: "%{count} events will be generated" accept: ok: Event accepted refuse: @@ -318,6 +324,10 @@ description." edit_link: "You can modify this event later to add details at the address:" delete_link: "You can can also cancel it at the address:" + repeat_helper: + zero: + one: Another event was genereated, here are the edition and cancellation links + other: "%{count} other events were generated, here are the edition and cancellation links" signature: Thank you for your contribution and see you soon! destroy: subject: "Event '%{subject}' refused" diff --git a/config/locales/views/fr.yml b/config/locales/views/fr.yml index 23955d1e..3b001d17 100644 --- a/config/locales/views/fr.yml +++ b/config/locales/views/fr.yml @@ -80,6 +80,8 @@ fr: ok: Votre événement a été mis à jour form: title_helper: Moins de 5 mots, sans lieu ou date + rule_helper: Les événements répétés seront générés lors de la + validation. Vous recevrez par mail les liens d'édition et d'annulation description_helper: Décrivez de la manière la plus complète possible votre événement address_helper: "*Associée à la ville et la région, elle générera une @@ -176,6 +178,10 @@ fr: ok: Oui ko: Modération tweet_helper: Un tweet sera publié, dont voici le contenu + repeat_helper: + zero: + one: Un autre événement sera généré + other: "%{count} autres événements seront générés" accept: ok: Événement accepté refuse: @@ -324,6 +330,10 @@ est maintenant visible à l'adresse:" ajouter des précisions en vous rendant à l'adresse:" delete_link: "Vous pouvez également l'annuler en vous rendant à l'adresse:" + repeat_helper: + zero: + one: Un autre événement a été généré, voici les liens d'édition et annulation + other: "%{count} autres événements ont été générés, voici les liens d'édition et annulation" signature: Merci de votre contribution et à bientôt! destroy: subject: "Événement '%{subject}' refusé" diff --git a/db/migrate/20160616190823_create_schedules.rb b/db/migrate/20160616190823_create_schedules.rb new file mode 100644 index 00000000..e718ef16 --- /dev/null +++ b/db/migrate/20160616190823_create_schedules.rb @@ -0,0 +1,9 @@ +# Manage a schedule for events, that will let adl create recurring events +class CreateSchedules < ActiveRecord::Migration + def change + add_column :events, :repeat, :integer, default: 0 + add_column :events, :rule, :text, default: 'daily' + # This column is there to manage scheduled events + add_reference :events, :event, index: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 4c0e4aba..ddd671bc 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20160409131029) do +ActiveRecord::Schema.define(version: 20160616190823) do create_table "active_admin_comments", force: :cascade do |t| t.string "namespace", limit: 255 @@ -59,19 +59,19 @@ ActiveRecord::Schema.define(version: 20160409131029) do add_index "cities", ["name"], name: "cities_name" create_table "events", force: :cascade do |t| - t.string "title", limit: 255, default: "", null: false - t.text "description", limit: 65535, null: false - t.datetime "start_time", null: false - t.datetime "end_time", null: false + t.string "title", limit: 255, default: "", null: false + t.text "description", limit: 65535, null: false + t.datetime "start_time", null: false + t.datetime "end_time", null: false t.string "city", limit: 255, default: "" - t.integer "region_id", limit: 4, default: 0, null: false - t.integer "locality", limit: 4, default: 0, null: false - t.string "url", limit: 255, default: "", null: false - t.string "contact", limit: 255, default: "", null: false - t.string "submitter", limit: 255, default: "", null: false - t.integer "moderated", limit: 4, default: 0, null: false - t.string "tags", limit: 255, default: "", null: false - t.string "secret", limit: 255, default: "", null: false + t.integer "region_id", limit: 4, default: 0, null: false + t.integer "locality", limit: 4, default: 0, null: false + t.string "url", limit: 255, default: "", null: false + t.string "contact", limit: 255, default: "", null: false + t.string "submitter", limit: 255, default: "", null: false + t.integer "moderated", limit: 4, default: 0, null: false + t.string "tags", limit: 255, default: "", null: false + t.string "secret", limit: 255, default: "", null: false t.datetime "decision_time" t.datetime "submission_time" t.string "moderator_mail_id", limit: 32 @@ -79,10 +79,15 @@ ActiveRecord::Schema.define(version: 20160409131029) do t.text "address", limit: 65535 t.float "latitude", limit: 24 t.float "longitude", limit: 24 - t.integer "lock_version", limit: 4, default: 0, null: false + t.integer "lock_version", limit: 4, default: 0, null: false t.string "place_name", limit: 255 + t.integer "count", default: 1 + t.integer "repeat", default: 0 + t.text "rule", default: "daily" + t.integer "event_id" end + add_index "events", ["event_id"], name: "index_events_on_event_id" add_index "events", ["start_time", "end_time"], name: "events_date" create_table "kinds", force: :cascade do |t| diff --git a/test/models/event_callbacks_test.rb b/test/models/event_callbacks_test.rb new file mode 100644 index 00000000..c7fff6c4 --- /dev/null +++ b/test/models/event_callbacks_test.rb @@ -0,0 +1,47 @@ +require 'test_helper' + +# Test event callbacks +class EventCallbacksTest < ActiveSupport::TestCase + setup do + ActionMailer::Base.default_url_options[:host] = 'localhost:3000' + + @event = events :one + end + + test 'schedule' do + @event = Event.new( + title: 'hello world', + start_time: Time.zone.now, end_time: Time.zone.now + 1.hour, + description: 'et hop!', + city: City.first, region: Region.first, + url: 'http://example.com', + contact: 'contact@example.com', + tags: 'hello world' + ) + assert_difference 'Event.count' do + assert @event.save, @event.errors.messages + end + end + + test 'moderation' do + @event = Event.new( + title: 'hello world', + start_time: Time.zone.now + 1.hour, end_time: Time.zone.now + 2.hours, + repeat: 1, rule: 'monthly', + description: 'et hop!', + city: City.first, region: Region.first, + url: 'http://example.com', + contact: 'contact@example.com', + tags: 'hello world' + ) + + assert @event.save, @event.errors.messages + assert !@event.moderated? + + assert_difference 'Event.count' do + @event.update moderated: 1 + end + + assert @event.moderated?, @event.errors.messages + end +end diff --git a/test/models/event_test.rb b/test/models/event_test.rb index e69c3f4c..5ea2f481 100644 --- a/test/models/event_test.rb +++ b/test/models/event_test.rb @@ -21,7 +21,9 @@ class EventTest < ActiveSupport::TestCase submitter: 'submitter@example.com', tags: 'hello world' ) - assert @event.save, @event.errors.messages + assert_difference 'Event.count' do + assert @event.save, @event.errors.messages + end assert_equal 32, @event.secret.size assert_equal 32, @event.moderator_mail_id.size