(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 
3 Likes

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.

7 Likes

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?

Edit:
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)
end
2 Likes

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
4 Likes

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)
7 Likes

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.

4 Likes

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
4 Likes

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
...                              ^