(Obsolete) Set category tracking level defaults historically

Nope. Using :normal results in an error:

  User Load (3.1ms)  SELECT "users".* FROM "users"
   (0.4ms)  SELECT "category_users"."category_id" FROM "category_users" WHERE "category_users"."user_id" = 121 AND "category_users"."notification_level" IS NULL
   (0.9ms)  SELECT "categories"."id" FROM "categories" WHERE (id in (10))
   (0.2ms)  BEGIN
  SQL (0.8ms)  INSERT INTO "category_users" ("user_id", "category_id") VALUES (121, 10) RETURNING "id"  [["user_id", 121], ["category_id", 10]]
   (0.2ms)  ROLLBACK
ActiveRecord::StatementInvalid: PG::NotNullViolation: ERROR:  null value in column "notification_level" violates not-null constraint
DETAIL:  Failing row contains (1271, 10, 121, null).
: INSERT INTO "category_users" ("user_id", "category_id") VALUES (121, 10) RETURNING "id"
from /home/vagrant/.rvm/gems/ruby-2.3.1/gems/rack-mini-profiler-0.10.1/lib/patches/db/pg.rb:90:in `exec'

My guess is that I don’t really want to set it as :regular but somehow to set it as not :watching.

The query is along the lines of:

builder.where('notification_level = :tracking')

Later on doing this does nothing cause there is no watching var to substitute.

builder.exec(watching: notification_levels[:watching]) 
1 Like

@sam, I’m afraid I don’t understand your answer. I’ve taken us a bit astray from the OT, but this is what I’m struggling with:

What are you trying to do, delete all the category user records for all users that have it set to watching and 5?

CategoryUser.where(category_id: 5, notification_level: CategoryUser.notification_levels[:watching]).delete_all 

I wouldn’t of said it like that, but YES! Holy cow, yes.

1 Like

It seems to do just what it says on the tin. Any adverse side-effects I should be aware of before trying this on production?

well, it junks that user pref, any user that set watching on category 5, will no longer have watching on category 5.

That sounds about right :slight_smile:

Thanks to everyone here for helping me. For those playing at home, here’s a summary of the last 15 posts or so.

How to make all users watch (or unwatch) a specific category through the rails console

Set your parameters:

# Levels → :tracking :watching :watching_first_post :muted
level = :watching
category_slug = "announcements"

And then, to make everyone watch (or whatever level you set) this category:

User.all.each do |user| CategoryUser.batch_set(user, level, [Category.find_by_slug(category_slug)]) end

Or to make everyone unwatch (or whatever level you set) this category:

CategoryUser.where(category_id: Category.find_by_slug(category_slug), notification_level: CategoryUser.notification_levels[level]).delete_all

And there you have it! :tada:

:warning: Warning: unlike the OP, this is a destructive change in the sense that it disregards users’ current settings.


This works for top-level categories, but if I use the slug of a sub-category, it gives me

> category = Category.find_by_slug(category_slug)
=> nil

How do you achieve the same for sub-categories?

I think I figured it out (thanks to this hint). This seems to work, but there might be a more elegant way (I don’t know how to define and hand over an array)

# levels: :watching :watching_first_post
level = :watching
category_slug = "local-news"
parent_category_slug = "news" # <== added
category = Category.find_by_slug(category_slug, parent_category_slug)
group_name = "trust_level_0" # all users
group = group = Group.find_by_name(group_name)

group.users.each do |user|
  watched_categories = CategoryUser.lookup(user, level).pluck(:category_id)
  CategoryUser.set_notification_level_for_category(user, CategoryUser.notification_levels[level], 
category.id) unless watched_categories.include?(category.id)

Is there a way to re-apply all default watching/tracking/email preferences to all users?

Not per-category as the commands here describe, but more like “here are the defaults for new users… go ahead & apply them to all users now”?

If I can save the time I have spent with this thread to someone in the future…

If you want to reset the notification level of a subcategory for all users from e.g. “muted” to “regular” (being regular a special case), this is what you need to do:

./launcher enter app
rails c

And then paste your version of

level = :muted
category_slug = "cats" # this is the subcategory
parent_category_slug = "mammals" # this is the parent category
CategoryUser.where(category_id: Category.find_by_slug(category_slug, parent_category_slug), notification_level: CategoryUser.notification_levels[level]).delete_all

Can this be modified to work in group PM inboxes? For example, I was on an extended vacation, and I’m now returning. I updated my notification state for a shared inbox to “tracking” so I didn’t have thousands of green notifications, and now I want to update the state for all messages back to “watching”.

1 Like

Courtesy of @sam, here’s the code to update the notification level for PMs historically. The following placeholders must be replaced: <user_id>, <group_id_1> ,<group_id_2>.

TopicUser.where('notification_level < 3 and user_id = <user_id> and topic_id in (select topic_id from topic_allowed_groups where group_id in (<group_id_1>,<group_id_2>) )').update_all(notification_level: 3)

Assuming that this still works, I’m wondering whether category permissions will be honoured here.

I have a number of restricted categories and whoever has access to any of those should be watching first post by default. So if I follow the above steps for each of those categories, will only only users who actually hsve access be watching them?

Category permissions are 100% followed.


Okay, just to double check: am I right in assuming that I can use the above procedure to add the category in question to all users but if a user doesn’t have access to that category it will remain ineffective and invisible for that user until the user gains access?

(My reasoning is based on how default categories watching (etc) works)

That is my understand, yes.

1 Like

How can this be made to work with a two-container setup? If I enter data there is no rails. And if I enter web_only I get NoMethodError: undefined method `id' for nil:NilClass.

Hm, I was searching for “staff”, to be on the safe side:

# rails c
[1] pry(main)> Category.find_by(name: "staff").id
NoMethodError: undefined method `id' for nil:NilClass
from (pry):1:in `__pry__'
[2] pry(main)>

Edit: Okay, got it: it’s case sensitive. This works:

Category.find_by(name: "Staff").id

Yesterday I discovered where our email volume of 100K+/mo was coming from… All new users were getting set as subscribed to our “General karting” category…

So I need to correct that…

I need some help with the syntax of part 1 in the OP. Bare with me here… I’m not exactly sure what I’m doing wrong…

I tried both " and ’ for quotations, but otherwise, I’m not sure what I need to correct in my syntax

[1] pry(main)> % Category.find_by(name: "General Karting").id
SyntaxError: unexpected ')', expecting end-of-input
...ind_by(name: "General Karting").id

… ^

[1] pry(main)> % Category.find_by(name: 'General Karting').id
SyntaxError: unexpected ')', expecting end-of-input
...ind_by(name: 'General Karting').id
...                              ^