]> git.openstreetmap.org Git - rails.git/blob - app/models/user_notification_preferences.rb
Merge remote-tracking branch 'upstream/pull/7110'
[rails.git] / app / models / user_notification_preferences.rb
1 # frozen_string_literal: true
2
3 class UserNotificationPreferences
4   extend ActiveModel::Naming
5   include ActiveModel::Conversion
6
7   EVENTS = %w[
8     changeset_comment
9     diary_comment
10     direct_message
11     gpx_import_failure
12     gpx_import_success
13     new_follower
14     note_comment
15   ].freeze
16
17   MECHANISMS = %w[
18     email
19   ].freeze
20
21   def initialize(user)
22     @user = user
23   end
24
25   # Receives a hash in the form `event => [mechanisms...]`. Eg:
26   # `{:changeset_comment => ["email"], :new_follower => []}`
27   def update(new_prefs)
28     updated_records =
29       EVENTS.map do |event_name|
30         MECHANISMS.filter_map do |mechanism|
31           next unless new_prefs.key?(event_name)
32
33           record = @user.preferences.find_or_initialize_by(:k => "notification.#{event_name}.#{mechanism}")
34           record.v = Array.wrap(new_prefs[event_name]).include?(mechanism)
35           record
36         end
37       end.flatten
38
39     UserPreference.transaction do
40       updated_records.each(&:save!)
41       true
42     end
43   end
44
45   # One getter method for each event. Required by ActionView
46   # to render the form, but also generally useful to us.
47   EVENTS.each do |event_name|
48     define_method event_name do
49       prefs =
50         @user
51         .preferences
52         .where("k LIKE 'notification.#{event_name}.%'")
53         .pluck(:k, :v)
54         .to_h
55         .transform_keys { |k| k.split(".").last }
56
57       MECHANISMS.filter do |mechanism|
58         prefs.key?(mechanism) ? ActiveModel::Type::Boolean.new.cast(prefs[mechanism]) : true
59       end
60     end
61   end
62 end