Events Plugin 📆

Hi @angus, there seems to be a bug with latest Discourse:

StandardError (Attempting to access a non preloaded custom field, this is disallowed to prevent N+1 queries.) /var/www/discourse/app/models/concerns/has_custom_fields.rb:158:in `[]'

/var/www/discourse/app/models/concerns/has_custom_fields.rb:158:in `[]'
/var/www/discourse/plugins/discourse-events/plugin.rb:69:in `events_enabled'
/var/www/discourse/plugins/discourse-events/plugin.rb:52:in `block (2 levels) in activate!'
(eval):31:in `_fast_attributes'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:468:in `rescue in attributes'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:455:in `attributes'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:480:in `_serializable_hash'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:359:in `serializable_hash'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer/associations.rb:124:in `block in serialize'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer/associations.rb:123:in `map'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer/associations.rb:123:in `serialize'
/var/www/discourse/lib/freedom_patches/ams_include_without_root.rb:55:in `include!'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:368:in `block in include_associations!'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:367:in `each_key'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:367:in `include_associations!'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:362:in `serializable_hash'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:347:in `as_json'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `encode'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `encode'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `to_json'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/active_model_serializers-0.8.4/lib/active_model/serializer.rb:331:in `to_json'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/multi_json-1.13.1/lib/multi_json/adapters/oj.rb:40:in `dump'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/multi_json-1.13.1/lib/multi_json/adapters/oj.rb:40:in `dump'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/multi_json-1.13.1/lib/multi_json/adapter.rb:25:in `dump'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/multi_json-1.13.1/lib/multi_json.rb:139:in `dump'
/var/www/discourse/app/models/site.rb:123:in `json_for'
/var/www/discourse/app/controllers/application_controller.rb:523:in `preload_anonymous_data'
/var/www/discourse/app/controllers/application_controller.rb:350:in `preload_json'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `block in make_lambda'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `block (2 levels) in halting'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `block (2 levels) in <module:Callbacks>'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `block in halting'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `block in invoke_before'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `each'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `invoke_before'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `process_action'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `process_action'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `block in process_action'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `block in instrument'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `instrument'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `instrument'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `process_action'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `process_action'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activerecord- `process_action'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `process'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionview- `process'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-mini-profiler-1.0.2/lib/mini_profiler/profiling_methods.rb:78:in `block in profile_method'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `dispatch'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `dispatch'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `dispatch'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `serve'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `block in serve'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `each'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `serve'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-protection-2.0.5/lib/rack/protection/frame_options.rb:31:in `call'
/var/www/discourse/lib/middleware/omniauth_bypass_middleware.rb:32:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-2.0.6/lib/rack/tempfile_reaper.rb:15:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-2.0.6/lib/rack/conditional_get.rb:25:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-2.0.6/lib/rack/head.rb:12:in `call'
/var/www/discourse/lib/content_security_policy/middleware.rb:12:in `call'
/var/www/discourse/lib/middleware/anonymous_cache.rb:214:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-2.0.6/lib/rack/session/abstract/id.rb:232:in `context'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-2.0.6/lib/rack/session/abstract/id.rb:226:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `block in call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/activesupport- `run_callbacks'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/logster-2.1.2/lib/logster/middleware/reporter.rb:30:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/railties- `call_app'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/railties- `call'
/var/www/discourse/config/initializers/100-quiet_logger.rb:16:in `call'
/var/www/discourse/config/initializers/100-silence_logger.rb:29:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/actionpack- `call'
/var/www/discourse/lib/middleware/enforce_hostname.rb:17:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-2.0.6/lib/rack/method_override.rb:22:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rails_multisite-2.0.6/lib/rails_multisite/middleware.rb:24:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-2.0.6/lib/rack/sendfile.rb:111:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-mini-profiler-1.0.2/lib/mini_profiler/profiler.rb:171:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/message_bus-2.2.0/lib/message_bus/rack/middleware.rb:57:in `call'
/var/www/discourse/lib/middleware/request_tracker.rb:163:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/railties- `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/railties- `public_send'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/railties- `method_missing'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-2.0.6/lib/rack/urlmap.rb:68:in `block in call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-2.0.6/lib/rack/urlmap.rb:53:in `each'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/rack-2.0.6/lib/rack/urlmap.rb:53:in `call'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/lib/unicorn/http_server.rb:606:in `process_client'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/lib/unicorn/http_server.rb:701:in `worker_loop'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/lib/unicorn/http_server.rb:549:in `spawn_missing_workers'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/lib/unicorn/http_server.rb:142:in `start'
/var/www/discourse/vendor/bundle/ruby/2.5.0/gems/unicorn-5.4.1/bin/unicorn:126:in `<top (required)>'
/var/www/discourse/vendor/bundle/ruby/2.5.0/bin/unicorn:23:in `load'
/var/www/discourse/vendor/bundle/ruby/2.5.0/bin/unicorn:23:in `<main>'

Although running in safe-mode does not fix it!

I guess this one is gonna help…


I had the same experience. Removing from app.yml and rebuilding was the fix for me.


That’s something you can somewhat do by putting the events in different categories. The event would have the category color on the main agenda, and you can filter the events by filtering the categories.

I think adding a feature as you are describing should be done with icons rather than colors, maybe with tags (adding an icon if the event has that specific tag). Ideally it would be out-of-the-box with the tag icon theme component.

1 Like

It works beautifully… thanks for this tip. I wonder if there is a way to also filter events by tags? As it is, though, this is quite robust.

@hellekin @tobiaseigen I just pushed an update to fix this issue.


That would indeed be super useful !

If there is a way to just use the usual thunderbird or other calendars with a login/pass, that would be very handy !


Hi @angus, I’ve found what looks like a bug. I’m not sure if it stems from the Events Plugin or core.

It comes from my specific use-case and the way I’m using the plugin so I’m not sure how widespread this will be amongst your users.

When you visit the unadorned category URL of a category that is set to display the Agenda you are no longer redirected to the route that you use in the Events Plugin.

For example, if I have a category a-category and my category settings state that my Default Topic List is set to Agenda, and I visit the base URL for that category…


I am no longer redirected to…


…as I used to be.

Instead, I am given a blank browser page and the console reports the following error.

Detailed log from Chome console

_ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3841 Uncaught t {stack: “Error: Can’t trigger action ‘refreshTitle’ because…61e7351258de8d2e886bf2ce86f144368848.js:16:22294)”, description: undefined, fileName: undefined, lineNumber: undefined, message: “Can’t trigger action ‘refreshTitle’ because your a…ssed to the model/beforeModel/afterModel hooks.”, …}code: undefineddescription: undefinedfileName: undefinedlineNumber: undefinedmessage: "Can’t trigger action ‘refreshTitle’ because your app hasn’t finished transitioning into its first route. To trigger an action on destination routes during a transition, you can call .send() on the Transition object passed to the model/beforeModel/afterModel hooks."name: "Error"number: undefinedstack: "Error: Can’t trigger action ‘refreshTitle’ because your app hasn’t finished transitioning into its first route. To trigger an action on destination routes during a transition, you can call .send() on the Transition object passed to the model/beforeModel/afterModel hooks.↵ at new t (↵ at n.T (↵ at u.triggerEvent (↵ at u.e.trigger (↵ at n.o.send (↵ at n. (↵ at b (↵ at n.trigger (↵ at↵ at e.invoke ("proto: Error
(anonymous) @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3841
setTimeout (async)
we.readyException @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3840
(anonymous) @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3860
p @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3548
h @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3616
setTimeout (async)
(anonymous) @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3654
c @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3282
fireWith @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3412
fire @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3420
c @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3282
fireWith @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3412
h @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3636
setTimeout (async)
(anonymous) @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3654
c @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3282
fireWith @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3412
fire @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3420
c @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3282
fireWith @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3412
ready @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3892
h @ _ember_jquery-5dbd79abddf53926275c73f77dbe61e7351258de8d2e886bf2ce86f144368848.js:3902

if I try to visit the full URL /c/a-category/l/agenda then it works as expected.

This is a change in behaviour between beta5 and beta7+7 (I just upgraded my test instance to beta7+7 and now I see this behaviour).

I am using your Custom Wizard Plugin redirect feature to redirect to this category which is why I mention my specific use case. I guess I can just change my code to append /l/agenda/ to get this working, but wanted to know if this is expected behaviour.

Finally, and oddly, if I locate the category in question in the category list from the home page and I hover over it with the mouse, I see that the URL it will take me to is in fact the unadorned version - i.e. /c/a-category.

However, when I click it, it works as expected and takes me to the /c/a-category/l/agenda page. If, instead of clicking the URL I copy the URL and paste it in to the browser, it fails as I described above. Some clever internal JavaScript redirection going on I guess?

I’m running 2.3.0 beta7+7 and the latest Events Plugin and am testing in Chrome Version 72.0.3626.96 (Official Build) (64-bit) on Ubuntu.

I’ve tried to repro on your sandbox but couldn’t find a category that is set to display the Agenda as the Default Topic List.


Thanks for a great bug report! I can indeed repro it on my sandbox, e.g.

This week is very busy, so I’m going to have to look at this next week:


Can we also add event rsvp improvements to your agenda? We are increasingly wanting to find alternatives to GoToWebinar for handling events, and this would be ideal. :rocket:

There’s one on Events agenda: Let me know specifically what else is needed.

This is now fixed. Turned out to be a bit of a hairy issue.

In other news, subscribing to calendar feeds of private categories is now supported. You have to add an appropriate api_key and api_username as query params to get it to work. For example:


Cool! That feature would be great and would go a long way to helping us. :rocket:

The task list you wrote above contained most the features I think we need. To repeat the key ones from there that would make this plugin work as eventbrite killer:

  • Guest rsvp
  • Event reminders
  • Event rsvp list export
  • Rsvp custom fields

Other items from your list that are interesting for this purpose:

  • Adding multiple events to one topic.
  • Recurring events

There are more items on that list where I am not sure of the status and would be glad of an update.

I’d be happy to review this topic for feature suggestions and update the OP with a proposed task list if you like, as I did for the ticket plugin. Let me know.


Cool, thanks. I’ve slotted in Guest RSVP, and moved Admin controls for RSVP list, which includes list export, up the agenda.

Multiple and recurring events are tricker / hairier, so I’ll take a look at them again in May, but can’t make any promises in that respect

I’ll also take a look at event reminders in May

RSVP custom fields will have to wait till June.


Hi everyone! Hi @angus!
Great plugin! Thanks a lot!

I think i found some issue. While approval post from “Needs Review” the date and time of event are lost.

While approval isn’t any information about date and time.

While editing post pending isn’t any information about date and time.

And after approval or save the date and time of event are lost. Have you some solution of that or maybe I’m doing something wrong?

Hi Marcin! Thanks for the detailed report.

I didn’t even realize you can edit posts via the review queue - that’s pretty cool!

Are you sure the event details are lost when approving posts? Or is it just not showing up there?

Generally, my thinking is that the events plugin is separate from the (very new) review queue functionality. The events plugin is not an official plugin and it is not integrated with other functionality, and so I don’t expect it to be. I’m not sure it really matters that you can’t see and edit event details via the review queue. You want to use the forum to read and manage discussions in any case, where you can always edit event details.

That said, if Angus is easily able to have the event details and edit modal show up in the review queue I can see how that can be useful. Not sure it’s a high priority, though, given his limited time and the other feature development on his task list. :sunny:

1 Like

I found an issue with the events plugin that only manifests if the following conditions are met:

  • Category settings
    • Navigate to first post after topics are read
    • Allow events to be added to topics in this category (overrides site setting).
  • Event type
    • Event is NOT an all day event

When all three are met, the topic doesn’t honour the ‘Navigate to first post’ any more. Other topics (without events or with all day events) in the same category work as expected.

Steps to repro:

  • configure category as described above
  • create new topic
  • add event date and time, do NOT set it to all day event
  • add few posts
  • return to category page, check that the topic is marked as read
  • click on topic title
  • last post is displayed (instead of the first one)

If event is removed or event duration is set to all day, the correct post (first) is displayed.

Great report, however I can’t repro this. I made an example topic in following your suggested steps. The “Navigate to first post after topics are read” setting works as normal.

See if you can reproduce it in that category? It has “Navigate to first post after topics are read” enabled.


Found it! :smile:

The date part of the title—the one that the event plugin appends to it—causes the issue (repro on your sandbox).

  • Clicking on the regular part of the topic title opens the first post
  • Clicking on the date part of the title opens the last post read.

Good catch! I took a quick look, but it’s actually a bit tricky. I’ll need to take a look at this one in some more depth the week after next.

1 Like

As scheduled, I’ve added the ability for event admins to add and remove users from an RSVP list:


Wow, Angus, this is amazing progress. Thanks!

Three bits of feedback:

  • the “Guest list” entry box is a bit confusing as an empty rectangle to start with - any way you could provide “add a user” helper text in the box to explain what can be done with it, like with starting a new message:
  • any way to be able to add email addresses to the field, creating a staged user, similar to the PM to staged user functionality?
  • are people on the guest list subscribed to the topic, e.g. are they watching the topic and notified of all replies because they rsvp’d?

And a bug: there seems to be a problem with Guest list being available to be filled in already while the topic is first being created. see screenshot for what happens. If I empty the “Guest list” box and save the topic, then return to edit and add users it works as expected.