PERF: shift most user options out of the user table
As it stands we load up user records quite frequently on the topic pages, this in turn pulls all the columns for the users being selected, just to discard them after they are loaded New structure keeps all options in a discrete table, this is better organised and allows us to easily add more column without worrying about bloating the user table
This commit is contained in:
parent
63cda22623
commit
3829c78526
|
@ -147,25 +147,29 @@ const User = RestModel.extend({
|
|||
'location',
|
||||
'name',
|
||||
'locale',
|
||||
'email_digests',
|
||||
'email_direct',
|
||||
'email_always',
|
||||
'email_private_messages',
|
||||
'dynamic_favicon',
|
||||
'digest_after_days',
|
||||
'new_topic_duration_minutes',
|
||||
'external_links_in_new_tab',
|
||||
'mailing_list_mode',
|
||||
'enable_quoting',
|
||||
'disable_jump_reply',
|
||||
'custom_fields',
|
||||
'user_fields',
|
||||
'muted_usernames',
|
||||
'profile_background',
|
||||
'card_background',
|
||||
'automatically_unpin_topics'
|
||||
'card_background'
|
||||
);
|
||||
|
||||
[ 'email_always',
|
||||
'mailing_list_mode',
|
||||
'external_links_in_new_tab',
|
||||
'email_digests',
|
||||
'email_direct',
|
||||
'email_private_messages',
|
||||
'dynamic_favicon',
|
||||
'enable_quoting',
|
||||
'disable_jump_reply',
|
||||
'automatically_unpin_topics',
|
||||
'digest_after_days'
|
||||
].forEach(s => {
|
||||
data[s] = this.get(`user_option.${s}`);
|
||||
});
|
||||
|
||||
['muted','watched','tracked'].forEach(s => {
|
||||
let cats = this.get(s + 'Categories').map(c => c.get('id'));
|
||||
// HACK: denote lack of categories
|
||||
|
@ -174,7 +178,7 @@ const User = RestModel.extend({
|
|||
});
|
||||
|
||||
if (!Discourse.SiteSettings.edit_history_visible_to_public) {
|
||||
data['edit_history_public'] = this.get('edit_history_public');
|
||||
data['edit_history_public'] = this.get('user_option.edit_history_public');
|
||||
}
|
||||
|
||||
// TODO: We can remove this when migrated fully to rest model.
|
||||
|
@ -184,7 +188,7 @@ const User = RestModel.extend({
|
|||
type: 'PUT'
|
||||
}).then(result => {
|
||||
this.set('bio_excerpt', result.user.bio_excerpt);
|
||||
const userProps = this.getProperties('enable_quoting', 'external_links_in_new_tab', 'dynamic_favicon');
|
||||
const userProps = Em.getProperties(this.get('user-option'),'enable_quoting', 'external_links_in_new_tab', 'dynamic_favicon');
|
||||
Discourse.User.current().setProperties(userProps);
|
||||
}).finally(() => {
|
||||
this.set('isSaving', false);
|
||||
|
|
|
@ -169,17 +169,17 @@
|
|||
<div class="control-group pref-email-settings">
|
||||
<label class="control-label">{{i18n 'user.email_settings'}}</label>
|
||||
{{#if canReceiveDigest}}
|
||||
{{preference-checkbox labelKey="user.email_digests.title" checked=model.email_digests}}
|
||||
{{#if model.email_digests}}
|
||||
{{preference-checkbox labelKey="user.email_digests.title" checked=model.user_option.email_digests}}
|
||||
{{#if model.user_option.email_digests}}
|
||||
<div class='controls controls-dropdown'>
|
||||
{{combo-box valueAttribute="value" content=digestFrequencies value=model.digest_after_days}}
|
||||
{{combo-box valueAttribute="value" content=digestFrequencies value=model.user_option.digest_after_days}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{preference-checkbox labelKey="user.email_private_messages" checked=model.email_private_messages}}
|
||||
{{preference-checkbox labelKey="user.email_direct" checked=model.email_direct}}
|
||||
<span class="pref-mailing-list-mode">{{preference-checkbox labelKey="user.mailing_list_mode" checked=model.mailing_list_mode}}</span>
|
||||
{{preference-checkbox labelKey="user.email_always" checked=model.email_always}}
|
||||
{{preference-checkbox labelKey="user.email_private_messages" checked=model.user_option.email_private_messages}}
|
||||
{{preference-checkbox labelKey="user.email_direct" checked=model.user_option.email_direct}}
|
||||
<span class="pref-mailing-list-mode">{{preference-checkbox labelKey="user.mailing_list_mode" checked=model.user_option.mailing_list_mode}}</span>
|
||||
{{preference-checkbox labelKey="user.email_always" checked=model.user_option.email_always}}
|
||||
|
||||
<div class='instructions'>
|
||||
{{#if siteSettings.email_time_window_mins}}
|
||||
|
@ -209,12 +209,12 @@
|
|||
{{combo-box valueAttribute="value" content=autoTrackDurations value=model.auto_track_topics_after_msecs}}
|
||||
</div>
|
||||
|
||||
{{preference-checkbox labelKey="user.external_links_in_new_tab" checked=model.external_links_in_new_tab}}
|
||||
{{preference-checkbox labelKey="user.enable_quoting" checked=model.enable_quoting}}
|
||||
{{preference-checkbox labelKey="user.dynamic_favicon" checked=model.dynamic_favicon}}
|
||||
{{preference-checkbox labelKey="user.disable_jump_reply" checked=model.disable_jump_reply}}
|
||||
{{preference-checkbox labelKey="user.external_links_in_new_tab" checked=model.user_option.external_links_in_new_tab}}
|
||||
{{preference-checkbox labelKey="user.enable_quoting" checked=model.user_option.enable_quoting}}
|
||||
{{preference-checkbox labelKey="user.dynamic_favicon" checked=model.user_option.dynamic_favicon}}
|
||||
{{preference-checkbox labelKey="user.disable_jump_reply" checked=model.user_option.disable_jump_reply}}
|
||||
{{#unless siteSettings.edit_history_visible_to_public}}
|
||||
{{preference-checkbox labelKey="user.edit_history_public" checked=model.edit_history_public}}
|
||||
{{preference-checkbox labelKey="user.edit_history_public" checked=model.user_option.edit_history_public}}
|
||||
{{/unless}}
|
||||
|
||||
{{plugin-outlet "user-custom-preferences"}}
|
||||
|
@ -254,7 +254,7 @@
|
|||
{{#if siteSettings.automatically_unpin_topics}}
|
||||
<div class="control-group topics">
|
||||
<label class="control-label">{{i18n 'categories.topics'}}</label>
|
||||
{{preference-checkbox labelKey="user.automatically_unpin_topics" checked=model.automatically_unpin_topics}}
|
||||
{{preference-checkbox labelKey="user.automatically_unpin_topics" checked=model.user_option.automatically_unpin_topics}}
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
|
|
|
@ -25,9 +25,12 @@ class EmailController < ApplicationController
|
|||
end
|
||||
|
||||
if params[:from_all]
|
||||
@user.update_columns(email_digests: false, email_direct: false, email_private_messages: false, email_always: false)
|
||||
@user.user_option.update_columns(email_always: false,
|
||||
email_digests: false,
|
||||
email_direct: false,
|
||||
email_private_messages: false)
|
||||
else
|
||||
@user.update_column(:email_digests, false)
|
||||
@user.user_option.update_column(:email_digests, false)
|
||||
end
|
||||
|
||||
@success = true
|
||||
|
@ -36,7 +39,7 @@ class EmailController < ApplicationController
|
|||
def resubscribe
|
||||
@user = DigestUnsubscribeKey.user_for_key(params[:key])
|
||||
raise Discourse::NotFound unless @user.present?
|
||||
@user.update_column(:email_digests, true)
|
||||
@user.user_option.update_column(:email_digests, true)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
@ -11,7 +11,8 @@ module Jobs
|
|||
|
||||
users =
|
||||
User.activated.not_blocked.not_suspended.real
|
||||
.where(mailing_list_mode: true)
|
||||
.joins(:user_option)
|
||||
.where(user_options: {mailing_list_mode: true})
|
||||
.where('NOT EXISTS(
|
||||
SELECT 1
|
||||
FROM topic_users tu
|
||||
|
|
|
@ -62,7 +62,7 @@ module Jobs
|
|||
return if user.staged && type == :digest
|
||||
|
||||
seen_recently = (user.last_seen_at.present? && user.last_seen_at > SiteSetting.email_time_window_mins.minutes.ago)
|
||||
seen_recently = false if user.email_always || user.staged
|
||||
seen_recently = false if user.user_option.email_always || user.staged
|
||||
|
||||
email_args = {}
|
||||
|
||||
|
@ -85,14 +85,14 @@ module Jobs
|
|||
email_args[:notification_type] = email_args[:notification_type].to_s
|
||||
end
|
||||
|
||||
if user.mailing_list_mode? &&
|
||||
if user.user_option.mailing_list_mode? &&
|
||||
!post.topic.private_message? &&
|
||||
NOTIFICATIONS_SENT_BY_MAILING_LIST.include?(email_args[:notification_type])
|
||||
# no need to log a reason when the mail was already sent via the mailing list job
|
||||
return [nil, nil]
|
||||
end
|
||||
|
||||
unless user.email_always?
|
||||
unless user.user_option.email_always?
|
||||
if (notification && notification.read?) || (post && post.seen?(user))
|
||||
return skip_message(I18n.t('email_log.notification_already_read'))
|
||||
end
|
||||
|
|
|
@ -15,8 +15,10 @@ module Jobs
|
|||
def target_user_ids
|
||||
# Users who want to receive emails and haven't been emailed in the last day
|
||||
query = User.real
|
||||
.where(email_digests: true, active: true, staged: false)
|
||||
.where(active: true, staged: false)
|
||||
.joins(:user_option)
|
||||
.not_suspended
|
||||
.where(user_options: {email_digests: true})
|
||||
.where("COALESCE(last_emailed_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 DAY'::INTERVAL * digest_after_days)")
|
||||
.where("COALESCE(last_seen_at, '2010-01-01') <= CURRENT_TIMESTAMP - ('1 DAY'::INTERVAL * digest_after_days)")
|
||||
.where("COALESCE(last_seen_at, '2010-01-01') >= CURRENT_TIMESTAMP - ('1 DAY'::INTERVAL * #{SiteSetting.delete_digest_email_after_days})")
|
||||
|
|
|
@ -321,7 +321,7 @@ class UserNotifications < ActionMailer::Base
|
|||
context: context,
|
||||
username: username,
|
||||
add_unsubscribe_link: !user.staged,
|
||||
add_unsubscribe_via_email_link: user.mailing_list_mode,
|
||||
add_unsubscribe_via_email_link: user.user_option.mailing_list_mode,
|
||||
unsubscribe_url: post.topic.unsubscribe_url,
|
||||
allow_reply_by_email: allow_reply_by_email,
|
||||
use_site_subject: use_site_subject,
|
||||
|
|
|
@ -38,6 +38,7 @@ class User < ActiveRecord::Base
|
|||
has_many :user_archived_messages, dependent: :destroy
|
||||
|
||||
|
||||
has_one :user_option, dependent: :destroy
|
||||
has_one :user_avatar, dependent: :destroy
|
||||
has_one :facebook_user_info, dependent: :destroy
|
||||
has_one :twitter_user_info, dependent: :destroy
|
||||
|
@ -80,6 +81,7 @@ class User < ActiveRecord::Base
|
|||
|
||||
after_create :create_email_token
|
||||
after_create :create_user_stat
|
||||
after_create :create_user_option
|
||||
after_create :create_user_profile
|
||||
after_create :ensure_in_trust_level_group
|
||||
after_create :automatic_group_membership
|
||||
|
@ -123,7 +125,7 @@ class User < ActiveRecord::Base
|
|||
|
||||
# TODO-PERF: There is no indexes on any of these
|
||||
# and NotifyMailingListSubscribers does a select-all-and-loop
|
||||
# may want to create an index on (active, blocked, suspended_till, mailing_list_mode)?
|
||||
# may want to create an index on (active, blocked, suspended_till)?
|
||||
scope :blocked, -> { where(blocked: true) }
|
||||
scope :not_blocked, -> { where(blocked: false) }
|
||||
scope :suspended, -> { where('suspended_till IS NOT NULL AND suspended_till > ?', Time.zone.now) }
|
||||
|
@ -911,6 +913,10 @@ class User < ActiveRecord::Base
|
|||
stat.save!
|
||||
end
|
||||
|
||||
def create_user_option
|
||||
UserOption.create(user_id: id)
|
||||
end
|
||||
|
||||
def create_email_token
|
||||
email_tokens.create(email: email)
|
||||
end
|
||||
|
@ -965,21 +971,8 @@ class User < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def set_default_user_preferences
|
||||
set_default_email_digest_frequency
|
||||
set_default_email_private_messages
|
||||
set_default_email_direct
|
||||
set_default_email_mailing_list_mode
|
||||
set_default_email_always
|
||||
|
||||
set_default_other_new_topic_duration_minutes
|
||||
set_default_other_auto_track_topics_after_msecs
|
||||
set_default_other_external_links_in_new_tab
|
||||
set_default_other_enable_quoting
|
||||
set_default_other_dynamic_favicon
|
||||
set_default_other_disable_jump_reply
|
||||
set_default_other_edit_history_public
|
||||
|
||||
set_default_topics_automatic_unpin
|
||||
|
||||
# needed, otherwise the callback chain is broken...
|
||||
true
|
||||
|
@ -1031,26 +1024,6 @@ class User < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
def set_default_email_digest_frequency
|
||||
if has_attribute?(:email_digests)
|
||||
if SiteSetting.default_email_digest_frequency.to_i <= 0
|
||||
self.email_digests = false
|
||||
else
|
||||
self.email_digests = true
|
||||
self.digest_after_days ||= SiteSetting.default_email_digest_frequency.to_i if has_attribute?(:digest_after_days)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def set_default_email_mailing_list_mode
|
||||
self.mailing_list_mode = SiteSetting.default_email_mailing_list_mode if has_attribute?(:mailing_list_mode)
|
||||
end
|
||||
|
||||
%w{private_messages direct always}.each do |s|
|
||||
define_method("set_default_email_#{s}") do
|
||||
self.send("email_#{s}=", SiteSetting.send("default_email_#{s}")) if has_attribute?("email_#{s}")
|
||||
end
|
||||
end
|
||||
|
||||
%w{new_topic_duration_minutes auto_track_topics_after_msecs}.each do |s|
|
||||
define_method("set_default_other_#{s}") do
|
||||
|
@ -1058,16 +1031,6 @@ class User < ActiveRecord::Base
|
|||
end
|
||||
end
|
||||
|
||||
%w{external_links_in_new_tab enable_quoting dynamic_favicon disable_jump_reply edit_history_public}.each do |s|
|
||||
define_method("set_default_other_#{s}") do
|
||||
self.send("#{s}=", SiteSetting.send("default_other_#{s}")) if has_attribute?(s)
|
||||
end
|
||||
end
|
||||
|
||||
def set_default_topics_automatic_unpin
|
||||
self.automatically_unpin_topics = SiteSetting.default_topics_automatic_unpin
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
# == Schema Information
|
||||
|
@ -1090,14 +1053,11 @@ end
|
|||
# last_seen_at :datetime
|
||||
# admin :boolean default(FALSE), not null
|
||||
# last_emailed_at :datetime
|
||||
# email_digests :boolean not null
|
||||
# trust_level :integer not null
|
||||
# email_private_messages :boolean default(TRUE)
|
||||
# email_direct :boolean default(TRUE), not null
|
||||
# approved :boolean default(FALSE), not null
|
||||
# approved_by_id :integer
|
||||
# approved_at :datetime
|
||||
# digest_after_days :integer
|
||||
# previous_visit_at :datetime
|
||||
# suspended_at :datetime
|
||||
# suspended_till :datetime
|
||||
|
@ -1107,24 +1067,16 @@ end
|
|||
# flag_level :integer default(0), not null
|
||||
# ip_address :inet
|
||||
# new_topic_duration_minutes :integer
|
||||
# external_links_in_new_tab :boolean not null
|
||||
# enable_quoting :boolean default(TRUE), not null
|
||||
# moderator :boolean default(FALSE)
|
||||
# blocked :boolean default(FALSE)
|
||||
# dynamic_favicon :boolean default(FALSE), not null
|
||||
# title :string(255)
|
||||
# uploaded_avatar_id :integer
|
||||
# email_always :boolean default(FALSE), not null
|
||||
# mailing_list_mode :boolean default(FALSE), not null
|
||||
# primary_group_id :integer
|
||||
# locale :string(10)
|
||||
# registration_ip_address :inet
|
||||
# last_redirected_to_top_at :datetime
|
||||
# disable_jump_reply :boolean default(FALSE), not null
|
||||
# edit_history_public :boolean default(FALSE), not null
|
||||
# trust_level_locked :boolean default(FALSE), not null
|
||||
# staged :boolean default(FALSE), not null
|
||||
# automatically_unpin_topics :boolean default(TRUE)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
|
|
@ -64,12 +64,12 @@ class UserEmailObserver < ActiveRecord::Observer
|
|||
EMAILABLE_POST_TYPES ||= Set.new [Post.types[:regular], Post.types[:whisper]]
|
||||
|
||||
def enqueue(type, delay=default_delay)
|
||||
return unless notification.user.email_direct?
|
||||
return unless notification.user.user_option.email_direct?
|
||||
perform_enqueue(type, delay)
|
||||
end
|
||||
|
||||
def enqueue_private(type, delay=private_delay)
|
||||
return unless notification.user.email_private_messages?
|
||||
return unless notification.user.user_option.email_private_messages?
|
||||
perform_enqueue(type, delay)
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
class UserOption < ActiveRecord::Base
|
||||
self.primary_key = :user_id
|
||||
belongs_to :user
|
||||
before_create :set_defaults
|
||||
|
||||
def set_defaults
|
||||
self.email_always = SiteSetting.default_email_always
|
||||
self.mailing_list_mode = SiteSetting.default_email_mailing_list_mode
|
||||
self.email_direct = SiteSetting.default_email_direct
|
||||
self.automatically_unpin_topics = SiteSetting.default_topics_automatic_unpin
|
||||
self.email_private_messages = SiteSetting.default_email_private_messages
|
||||
|
||||
self.enable_quoting = SiteSetting.default_other_enable_quoting
|
||||
self.external_links_in_new_tab = SiteSetting.default_other_external_links_in_new_tab
|
||||
self.dynamic_favicon = SiteSetting.default_other_dynamic_favicon
|
||||
self.disable_jump_reply = SiteSetting.default_other_disable_jump_reply
|
||||
self.edit_history_public = SiteSetting.default_other_edit_history_public
|
||||
|
||||
|
||||
if SiteSetting.default_email_digest_frequency.to_i <= 0
|
||||
self.email_digests = false
|
||||
else
|
||||
self.email_digests = true
|
||||
self.digest_after_days ||= SiteSetting.default_email_digest_frequency.to_i
|
||||
end
|
||||
|
||||
true
|
||||
end
|
||||
end
|
|
@ -31,7 +31,8 @@ class CurrentUserSerializer < BasicUserSerializer
|
|||
:is_anonymous,
|
||||
:post_queue_new_count,
|
||||
:show_queued_posts,
|
||||
:read_faq
|
||||
:read_faq,
|
||||
:automatically_unpin_topics
|
||||
|
||||
def include_site_flagged_posts_count?
|
||||
object.staff?
|
||||
|
@ -49,6 +50,26 @@ class CurrentUserSerializer < BasicUserSerializer
|
|||
object.user_stat.topic_reply_count
|
||||
end
|
||||
|
||||
def enable_quoting
|
||||
object.user_option.enable_quoting
|
||||
end
|
||||
|
||||
def disable_jump_reply
|
||||
object.user_option.disable_jump_reply
|
||||
end
|
||||
|
||||
def external_links_in_new_tab
|
||||
object.user_option.external_links_in_new_tab
|
||||
end
|
||||
|
||||
def dynamic_favicon
|
||||
object.user_option.dynamic_favicon
|
||||
end
|
||||
|
||||
def automatically_unpin_topics
|
||||
object.user_option.automatically_unpin_topics
|
||||
end
|
||||
|
||||
def site_flagged_posts_count
|
||||
PostAction.flagged_posts_count
|
||||
end
|
||||
|
|
|
@ -0,0 +1,20 @@
|
|||
class UserOptionSerializer < ApplicationSerializer
|
||||
attributes :user_id,
|
||||
:email_always,
|
||||
:mailing_list_mode,
|
||||
:email_digests,
|
||||
:email_private_messages,
|
||||
:email_direct,
|
||||
:external_links_in_new_tab,
|
||||
:dynamic_favicon,
|
||||
:enable_quoting,
|
||||
:disable_jump_reply,
|
||||
:digest_after_days,
|
||||
:automatically_unpin_topics,
|
||||
:edit_history_public
|
||||
|
||||
|
||||
def include_edit_history_public?
|
||||
!SiteSetting.edit_history_visible_to_public
|
||||
end
|
||||
end
|
|
@ -61,40 +61,33 @@ class UserSerializer < BasicUserSerializer
|
|||
:uploaded_avatar_id,
|
||||
:badge_count,
|
||||
:has_title_badges,
|
||||
:edit_history_public,
|
||||
:custom_fields,
|
||||
:user_fields,
|
||||
:topic_post_count,
|
||||
:pending_count,
|
||||
:profile_view_count,
|
||||
:automatically_unpin_topics
|
||||
:profile_view_count
|
||||
|
||||
has_one :invited_by, embed: :object, serializer: BasicUserSerializer
|
||||
has_many :groups, embed: :object, serializer: BasicGroupSerializer
|
||||
has_many :featured_user_badges, embed: :ids, serializer: UserBadgeSerializer, root: :user_badges
|
||||
has_one :card_badge, embed: :object, serializer: BadgeSerializer
|
||||
has_one :user_option, embed: :object, serializer: UserOptionSerializer
|
||||
|
||||
def include_user_option?
|
||||
can_edit
|
||||
end
|
||||
|
||||
staff_attributes :post_count,
|
||||
:can_be_deleted,
|
||||
:can_delete_all_posts
|
||||
|
||||
private_attributes :locale,
|
||||
:email_digests,
|
||||
:email_private_messages,
|
||||
:email_direct,
|
||||
:email_always,
|
||||
:digest_after_days,
|
||||
:mailing_list_mode,
|
||||
:auto_track_topics_after_msecs,
|
||||
:new_topic_duration_minutes,
|
||||
:external_links_in_new_tab,
|
||||
:dynamic_favicon,
|
||||
:enable_quoting,
|
||||
:muted_category_ids,
|
||||
:tracked_category_ids,
|
||||
:watched_category_ids,
|
||||
:private_messages_stats,
|
||||
:disable_jump_reply,
|
||||
:system_avatar_upload_id,
|
||||
:system_avatar_template,
|
||||
:gravatar_avatar_upload_id,
|
||||
|
@ -322,10 +315,6 @@ class UserSerializer < BasicUserSerializer
|
|||
object.badges.where(allow_title: true).count > 0
|
||||
end
|
||||
|
||||
def include_edit_history_public?
|
||||
can_edit && !SiteSetting.edit_history_visible_to_public
|
||||
end
|
||||
|
||||
def user_fields
|
||||
object.user_fields
|
||||
end
|
||||
|
|
|
@ -40,11 +40,14 @@ class AnonymousShadowCreator
|
|||
active: true,
|
||||
trust_level: 1,
|
||||
trust_level_locked: true,
|
||||
email_private_messages: false,
|
||||
email_digests: false,
|
||||
created_at: 1.day.ago # bypass new user restrictions
|
||||
)
|
||||
|
||||
shadow.user_option.update_columns(
|
||||
email_private_messages: false,
|
||||
email_digests: false
|
||||
)
|
||||
|
||||
shadow.email_tokens.update_all(confirmed: true)
|
||||
shadow.activate
|
||||
|
||||
|
|
|
@ -23,14 +23,17 @@ class UserAnonymizer
|
|||
@user.name = nil
|
||||
@user.date_of_birth = nil
|
||||
@user.title = nil
|
||||
@user.email_digests = false
|
||||
@user.email_private_messages = false
|
||||
@user.email_direct = false
|
||||
@user.email_always = false
|
||||
@user.mailing_list_mode = false
|
||||
@user.uploaded_avatar_id = nil
|
||||
@user.save
|
||||
|
||||
options = @user.user_option
|
||||
options.email_always = false
|
||||
options.mailing_list_mode = false
|
||||
options.email_digests = false
|
||||
options.email_private_messages = false
|
||||
options.email_direct = false
|
||||
options.save
|
||||
|
||||
profile = @user.user_profile
|
||||
profile.destroy if profile
|
||||
@user.create_user_profile
|
||||
|
|
|
@ -6,18 +6,19 @@ class UserUpdater
|
|||
muted_category_ids: :muted
|
||||
}
|
||||
|
||||
USER_ATTR = [
|
||||
:email_digests,
|
||||
OPTION_ATTR = [
|
||||
:email_always,
|
||||
:mailing_list_mode,
|
||||
:email_digests,
|
||||
:email_direct,
|
||||
:email_private_messages,
|
||||
:external_links_in_new_tab,
|
||||
:enable_quoting,
|
||||
:dynamic_favicon,
|
||||
:mailing_list_mode,
|
||||
:disable_jump_reply,
|
||||
:edit_history_public,
|
||||
:automatically_unpin_topics,
|
||||
:digest_after_days
|
||||
]
|
||||
|
||||
def initialize(actor, user)
|
||||
|
@ -36,7 +37,6 @@ class UserUpdater
|
|||
|
||||
user.name = attributes.fetch(:name) { user.name }
|
||||
user.locale = attributes.fetch(:locale) { user.locale }
|
||||
user.digest_after_days = attributes.fetch(:digest_after_days) { user.digest_after_days }
|
||||
|
||||
if attributes[:auto_track_topics_after_msecs]
|
||||
user.auto_track_topics_after_msecs = attributes[:auto_track_topics_after_msecs].to_i
|
||||
|
@ -56,9 +56,19 @@ class UserUpdater
|
|||
end
|
||||
end
|
||||
|
||||
USER_ATTR.each do |attribute|
|
||||
|
||||
save_options = false
|
||||
OPTION_ATTR.each do |attribute|
|
||||
if attributes[attribute].present?
|
||||
user.send("#{attribute}=", attributes[attribute] == 'true')
|
||||
save_options = true
|
||||
|
||||
|
||||
if [true,false].include?(user.user_option.send(attribute))
|
||||
val = attributes[attribute].to_s == 'true'
|
||||
user.user_option.send("#{attribute}=", val)
|
||||
else
|
||||
user.user_option.send("#{attribute}=", attributes[attribute])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -72,7 +82,7 @@ class UserUpdater
|
|||
update_muted_users(attributes[:muted_usernames])
|
||||
end
|
||||
|
||||
user_profile.save && user.save
|
||||
(!save_options || user.user_option.save) && user_profile.save && user.save
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -16,12 +16,15 @@ User.seed do |u|
|
|||
u.active = true
|
||||
u.admin = true
|
||||
u.moderator = true
|
||||
u.email_direct = false
|
||||
u.approved = true
|
||||
u.email_private_messages = false
|
||||
u.trust_level = TrustLevel[4]
|
||||
end
|
||||
|
||||
UserOption.where(user_id: -1).update_all(
|
||||
email_private_messages: false,
|
||||
email_direct: false
|
||||
)
|
||||
|
||||
Group.user_trust_level_change!(-1, TrustLevel[4])
|
||||
|
||||
# User for the smoke tests
|
||||
|
@ -49,3 +52,4 @@ if ENV["SMOKE"] == "1"
|
|||
et.confirmed = true
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
class AddUserOptions < ActiveRecord::Migration
|
||||
def up
|
||||
|
||||
create_table :user_options, id: false do |t|
|
||||
t.integer :user_id, null: false
|
||||
t.boolean :email_always, null: false, default: false
|
||||
t.boolean :mailing_list_mode, null: false, default: false
|
||||
t.boolean :email_digests
|
||||
t.boolean :email_direct, null: false, default: true
|
||||
t.boolean :email_private_messages, null: false, default: true
|
||||
t.boolean :external_links_in_new_tab, null: false, default: false
|
||||
t.boolean :enable_quoting, null: false, default: true
|
||||
t.boolean :dynamic_favicon, null: false, default: false
|
||||
t.boolean :disable_jump_reply, null: false, default: false
|
||||
t.boolean :edit_history_public, null: false, default: false
|
||||
t.boolean :automatically_unpin_topics, null: false, default: true
|
||||
t.integer :digest_after_days
|
||||
end
|
||||
|
||||
add_index :user_options, [:user_id], unique: true
|
||||
|
||||
execute <<SQL
|
||||
INSERT INTO user_options (
|
||||
user_id,
|
||||
email_always,
|
||||
mailing_list_mode,
|
||||
email_digests,
|
||||
email_direct,
|
||||
email_private_messages,
|
||||
external_links_in_new_tab,
|
||||
enable_quoting,
|
||||
dynamic_favicon,
|
||||
disable_jump_reply,
|
||||
edit_history_public,
|
||||
automatically_unpin_topics,
|
||||
digest_after_days
|
||||
)
|
||||
SELECT id,
|
||||
email_always,
|
||||
mailing_list_mode,
|
||||
email_digests,
|
||||
email_direct,
|
||||
email_private_messages,
|
||||
external_links_in_new_tab,
|
||||
enable_quoting,
|
||||
dynamic_favicon,
|
||||
disable_jump_reply,
|
||||
edit_history_public,
|
||||
automatically_unpin_topics,
|
||||
digest_after_days
|
||||
FROM users
|
||||
SQL
|
||||
|
||||
# these can not be removed until a bit later
|
||||
# if we remove them now all currently running unicorns will start erroring out
|
||||
#
|
||||
# remove_column :users, :email_always
|
||||
# remove_column :users, :mailing_list_mode
|
||||
# remove_column :users, :email_digests
|
||||
# remove_column :users, :email_direct
|
||||
# remove_column :users, :email_private_messages
|
||||
# remove_column :users, :external_links_in_new_tab
|
||||
# remove_column :users, :enable_quoting
|
||||
# remove_column :users, :dynamic_favicon
|
||||
# remove_column :users, :disable_jump_reply
|
||||
# remove_column :users, :edit_history_public
|
||||
# remove_column :users, :automatically_unpin_topics
|
||||
# remove_column :users, :digest_after_days
|
||||
end
|
||||
|
||||
def down
|
||||
# we can not move backwards here cause columns
|
||||
# get removed an hour after the migration
|
||||
raise ActiveRecord::IrreversibleMigration
|
||||
end
|
||||
end
|
|
@ -157,7 +157,7 @@ module PostGuardian
|
|||
return false unless post
|
||||
|
||||
if !post.hidden
|
||||
return true if post.wiki || SiteSetting.edit_history_visible_to_public || post.user.try(:edit_history_public)
|
||||
return true if post.wiki || SiteSetting.edit_history_visible_to_public || (post.user && post.user.user_option.edit_history_public)
|
||||
end
|
||||
|
||||
authenticated? &&
|
||||
|
|
|
@ -510,7 +510,7 @@ describe Guardian do
|
|||
|
||||
it 'is true if the author has public edit history' do
|
||||
public_post_revision = Fabricate(:post_revision)
|
||||
public_post_revision.post.user.edit_history_public = true
|
||||
public_post_revision.post.user.user_option.edit_history_public = true
|
||||
expect(Guardian.new.can_see?(public_post_revision)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
@ -533,7 +533,7 @@ describe Guardian do
|
|||
|
||||
it 'is true if the author has public edit history' do
|
||||
public_post_revision = Fabricate(:post_revision)
|
||||
public_post_revision.post.user.edit_history_public = true
|
||||
public_post_revision.post.user.user_option.edit_history_public = true
|
||||
expect(Guardian.new.can_see?(public_post_revision)).to be_truthy
|
||||
end
|
||||
end
|
||||
|
|
|
@ -21,7 +21,11 @@ describe EmailController do
|
|||
|
||||
context '.resubscribe' do
|
||||
|
||||
let(:user) { Fabricate(:user, email_digests: false) }
|
||||
let(:user) {
|
||||
user = Fabricate(:user)
|
||||
user.user_option.update_columns(email_digests: false)
|
||||
user
|
||||
}
|
||||
let(:key) { DigestUnsubscribeKey.create_key_for(user) }
|
||||
|
||||
context 'with a valid key' do
|
||||
|
@ -31,7 +35,7 @@ describe EmailController do
|
|||
end
|
||||
|
||||
it 'subscribes the user' do
|
||||
expect(user.email_digests).to eq(true)
|
||||
expect(user.user_option.email_digests).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -39,7 +43,11 @@ describe EmailController do
|
|||
|
||||
context '.unsubscribe' do
|
||||
|
||||
let(:user) { Fabricate(:user, email_digests: true, email_direct: true, email_private_messages: true, email_always: true) }
|
||||
let(:user) {
|
||||
user = Fabricate(:user)
|
||||
user.user_option.update_columns(email_always: true, email_digests: true, email_direct: true, email_private_messages: true)
|
||||
user
|
||||
}
|
||||
let(:key) { DigestUnsubscribeKey.create_key_for(user) }
|
||||
|
||||
context 'from confirm unsubscribe email' do
|
||||
|
@ -49,10 +57,11 @@ describe EmailController do
|
|||
end
|
||||
|
||||
it 'unsubscribes from all emails' do
|
||||
expect(user.email_digests).to eq false
|
||||
expect(user.email_direct).to eq false
|
||||
expect(user.email_private_messages).to eq false
|
||||
expect(user.email_always).to eq false
|
||||
options = user.user_option
|
||||
expect(options.email_digests).to eq false
|
||||
expect(options.email_direct).to eq false
|
||||
expect(options.email_private_messages).to eq false
|
||||
expect(options.email_always).to eq false
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -63,7 +72,7 @@ describe EmailController do
|
|||
end
|
||||
|
||||
it 'unsubscribes the user' do
|
||||
expect(user.email_digests).to eq(false)
|
||||
expect(user.user_option.email_digests).to eq(false)
|
||||
end
|
||||
|
||||
it "sets the appropriate instance variables" do
|
||||
|
@ -90,7 +99,7 @@ describe EmailController do
|
|||
end
|
||||
|
||||
it 'does not unsubscribe the user' do
|
||||
expect(user.email_digests).to eq(true)
|
||||
expect(user.user_option.email_digests).to eq(true)
|
||||
end
|
||||
|
||||
it 'sets the appropriate instance variables' do
|
||||
|
@ -108,7 +117,7 @@ describe EmailController do
|
|||
end
|
||||
|
||||
it 'unsubscribes the user' do
|
||||
expect(user.email_digests).to eq(false)
|
||||
expect(user.user_option.email_digests).to eq(false)
|
||||
end
|
||||
|
||||
it 'sets the appropriate instance variables' do
|
||||
|
|
|
@ -55,7 +55,8 @@ describe Jobs::UserEmail do
|
|||
end
|
||||
|
||||
it "does send an email to a user that's been recently seen but has email_always set" do
|
||||
user.update_attributes(last_seen_at: 9.minutes.ago, email_always: true)
|
||||
user.update_attributes(last_seen_at: 9.minutes.ago)
|
||||
user.user_option.update_attributes(email_always: true)
|
||||
Email::Sender.any_instance.expects(:send)
|
||||
Jobs::UserEmail.new.execute(type: :user_replied, user_id: user.id, post_id: post.id)
|
||||
end
|
||||
|
@ -188,13 +189,13 @@ describe Jobs::UserEmail do
|
|||
it "does send the email if the notification has been seen but the user is set for email_always" do
|
||||
Email::Sender.any_instance.expects(:send)
|
||||
notification.update_column(:read, true)
|
||||
user.update_column(:email_always, true)
|
||||
user.user_option.update_column(:email_always, true)
|
||||
Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_id: notification.id)
|
||||
end
|
||||
|
||||
it "doesn't send the mail if the user is using mailing list mode" do
|
||||
Email::Sender.any_instance.expects(:send).never
|
||||
user.update_column(:mailing_list_mode, true)
|
||||
user.user_option.update_column(:mailing_list_mode, true)
|
||||
# sometimes, we pass the notification_id
|
||||
Jobs::UserEmail.new.execute(type: :user_mentioned, user_id: user.id, notification_id: notification.id, post_id: post.id)
|
||||
# other times, we only pass the type of notification
|
||||
|
|
|
@ -51,7 +51,7 @@ describe UserEmailObserver do
|
|||
include_examples "enqueue"
|
||||
|
||||
it "doesn't enqueue a job if the user has mention emails disabled" do
|
||||
notification.user.expects(:email_direct?).returns(false)
|
||||
notification.user.user_option.update_columns(email_direct: false)
|
||||
Jobs.expects(:enqueue_in).with(delay, :user_email, has_entry(type: type)).never
|
||||
UserEmailObserver.process_notification(notification)
|
||||
end
|
||||
|
@ -61,7 +61,7 @@ describe UserEmailObserver do
|
|||
include_examples "enqueue"
|
||||
|
||||
it "doesn't enqueue a job if the user has private message emails disabled" do
|
||||
notification.user.expects(:email_private_messages?).returns(false)
|
||||
notification.user.user_option.update_columns(email_private_messages: false)
|
||||
Jobs.expects(:enqueue_in).with(delay, :user_email, has_entry(type: type)).never
|
||||
UserEmailObserver.process_notification(notification)
|
||||
end
|
||||
|
|
|
@ -152,15 +152,15 @@ describe User do
|
|||
it "is properly initialized" do
|
||||
expect(subject.approved_at).to be_blank
|
||||
expect(subject.approved_by_id).to be_blank
|
||||
expect(subject.email_private_messages).to eq(true)
|
||||
expect(subject.email_direct).to eq(true)
|
||||
end
|
||||
|
||||
context 'after_save' do
|
||||
before { subject.save }
|
||||
|
||||
it "has an email token" do
|
||||
it "has correct settings" do
|
||||
expect(subject.email_tokens).to be_present
|
||||
expect(subject.user_option.email_private_messages).to eq(true)
|
||||
expect(subject.user_option.email_direct).to eq(true)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -1246,50 +1246,62 @@ describe User do
|
|||
context "when user preferences are overriden" do
|
||||
|
||||
before do
|
||||
SiteSetting.stubs(:default_email_digest_frequency).returns(1) # daily
|
||||
SiteSetting.stubs(:default_email_private_messages).returns(false)
|
||||
SiteSetting.stubs(:default_email_direct).returns(false)
|
||||
SiteSetting.stubs(:default_email_mailing_list_mode).returns(true)
|
||||
SiteSetting.stubs(:default_email_always).returns(true)
|
||||
SiteSetting.default_email_digest_frequency = 1 # daily
|
||||
SiteSetting.default_email_private_messages = false
|
||||
SiteSetting.default_email_direct = false
|
||||
SiteSetting.default_email_mailing_list_mode = true
|
||||
SiteSetting.default_email_always = true
|
||||
|
||||
SiteSetting.stubs(:default_other_new_topic_duration_minutes).returns(-1) # not viewed
|
||||
SiteSetting.stubs(:default_other_auto_track_topics_after_msecs).returns(0) # immediately
|
||||
SiteSetting.stubs(:default_other_external_links_in_new_tab).returns(true)
|
||||
SiteSetting.stubs(:default_other_enable_quoting).returns(false)
|
||||
SiteSetting.stubs(:default_other_dynamic_favicon).returns(true)
|
||||
SiteSetting.stubs(:default_other_disable_jump_reply).returns(true)
|
||||
SiteSetting.stubs(:default_other_edit_history_public).returns(true)
|
||||
SiteSetting.default_other_new_topic_duration_minutes = -1 # not viewed
|
||||
SiteSetting.default_other_auto_track_topics_after_msecs = 0 # immediately
|
||||
SiteSetting.default_other_external_links_in_new_tab = true
|
||||
SiteSetting.default_other_enable_quoting = false
|
||||
SiteSetting.default_other_dynamic_favicon = true
|
||||
SiteSetting.default_other_disable_jump_reply = true
|
||||
SiteSetting.default_other_edit_history_public = true
|
||||
|
||||
SiteSetting.stubs(:default_topics_automatic_unpin).returns(false)
|
||||
SiteSetting.default_topics_automatic_unpin = false
|
||||
|
||||
SiteSetting.stubs(:default_categories_watching).returns("1")
|
||||
SiteSetting.stubs(:default_categories_tracking).returns("2")
|
||||
SiteSetting.stubs(:default_categories_muted).returns("3")
|
||||
SiteSetting.default_categories_watching = "1"
|
||||
SiteSetting.default_categories_tracking = "2"
|
||||
SiteSetting.default_categories_muted = "3"
|
||||
end
|
||||
|
||||
it "has overriden preferences" do
|
||||
user = Fabricate(:user)
|
||||
|
||||
expect(user.digest_after_days).to eq(1)
|
||||
expect(user.email_private_messages).to eq(false)
|
||||
expect(user.email_direct).to eq(false)
|
||||
expect(user.mailing_list_mode).to eq(true)
|
||||
expect(user.email_always).to eq(true)
|
||||
options = user.user_option
|
||||
expect(options.email_always).to eq(true)
|
||||
expect(options.mailing_list_mode).to eq(true)
|
||||
expect(options.digest_after_days).to eq(1)
|
||||
expect(options.email_private_messages).to eq(false)
|
||||
expect(options.external_links_in_new_tab).to eq(true)
|
||||
expect(options.enable_quoting).to eq(false)
|
||||
expect(options.dynamic_favicon).to eq(true)
|
||||
expect(options.disable_jump_reply).to eq(true)
|
||||
expect(options.edit_history_public).to eq(true)
|
||||
expect(options.automatically_unpin_topics).to eq(false)
|
||||
expect(options.email_direct).to eq(false)
|
||||
|
||||
expect(user.new_topic_duration_minutes).to eq(-1)
|
||||
expect(user.auto_track_topics_after_msecs).to eq(0)
|
||||
expect(user.external_links_in_new_tab).to eq(true)
|
||||
expect(user.enable_quoting).to eq(false)
|
||||
expect(user.dynamic_favicon).to eq(true)
|
||||
expect(user.disable_jump_reply).to eq(true)
|
||||
expect(user.edit_history_public).to eq(true)
|
||||
|
||||
expect(user.automatically_unpin_topics).to eq(false)
|
||||
|
||||
expect(CategoryUser.lookup(user, :watching).pluck(:category_id)).to eq([1])
|
||||
expect(CategoryUser.lookup(user, :tracking).pluck(:category_id)).to eq([2])
|
||||
expect(CategoryUser.lookup(user, :muted).pluck(:category_id)).to eq([3])
|
||||
end
|
||||
end
|
||||
|
||||
context UserOption do
|
||||
|
||||
it "Creates a UserOption row when a user record is created and destroys once done" do
|
||||
user = Fabricate(:user)
|
||||
expect(user.user_option.email_always).to eq(false)
|
||||
|
||||
user_id = user.id
|
||||
user.destroy!
|
||||
expect(UserOption.find_by(user_id: user_id)).to eq(nil)
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
@ -15,6 +15,24 @@ describe UserSerializer do
|
|||
end
|
||||
end
|
||||
|
||||
context "as current user" do
|
||||
it "serializes options correctly" do
|
||||
# so we serialize more stuff
|
||||
SiteSetting.edit_history_visible_to_public = false
|
||||
|
||||
user = Fabricate.build(:user,
|
||||
user_profile: Fabricate.build(:user_profile),
|
||||
user_option: UserOption.new(edit_history_public: true),
|
||||
user_stat: UserStat.new
|
||||
)
|
||||
|
||||
json = UserSerializer.new(user, scope: Guardian.new(user), root: false).as_json
|
||||
|
||||
expect(json[:user_option][:edit_history_public]).to eq(true)
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
context "with a user" do
|
||||
let(:user) { Fabricate.build(:user, user_profile: Fabricate.build(:user_profile) ) }
|
||||
let(:serializer) { UserSerializer.new(user, scope: Guardian.new, root: false) }
|
||||
|
@ -26,7 +44,7 @@ describe UserSerializer do
|
|||
|
||||
context "with `enable_names` true" do
|
||||
before do
|
||||
SiteSetting.stubs(:enable_names?).returns(true)
|
||||
SiteSetting.enable_names = true
|
||||
end
|
||||
|
||||
it "has a name" do
|
||||
|
@ -34,6 +52,7 @@ describe UserSerializer do
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
context "with `enable_names` false" do
|
||||
before do
|
||||
SiteSetting.stubs(:enable_names?).returns(false)
|
||||
|
|
|
@ -30,6 +30,9 @@ describe AnonymousShadowCreator do
|
|||
freeze_time 4.minutes.from_now
|
||||
shadow3 = AnonymousShadowCreator.get(user)
|
||||
|
||||
expect(shadow3.user_option.email_digests).to eq(false)
|
||||
expect(shadow3.user_option.email_private_messages).to eq(false)
|
||||
|
||||
expect(shadow2.id).not_to eq(shadow3.id)
|
||||
|
||||
end
|
||||
|
|
|
@ -19,13 +19,17 @@ describe UserAnonymizer do
|
|||
end
|
||||
|
||||
it "turns off all notifications" do
|
||||
user.user_option.update_columns(
|
||||
email_always: true
|
||||
)
|
||||
|
||||
make_anonymous
|
||||
user.reload
|
||||
expect(user.email_digests).to eq(false)
|
||||
expect(user.email_private_messages).to eq(false)
|
||||
expect(user.email_direct).to eq(false)
|
||||
expect(user.email_always).to eq(false)
|
||||
expect(user.mailing_list_mode).to eq(false)
|
||||
expect(user.user_option.email_digests).to eq(false)
|
||||
expect(user.user_option.email_private_messages).to eq(false)
|
||||
expect(user.user_option.email_direct).to eq(false)
|
||||
expect(user.user_option.email_always).to eq(false)
|
||||
expect(user.user_option.mailing_list_mode).to eq(false)
|
||||
end
|
||||
|
||||
it "resets profile to default values" do
|
||||
|
|
|
@ -32,26 +32,33 @@ describe UserUpdater do
|
|||
describe '#update' do
|
||||
it 'saves user' do
|
||||
user = Fabricate(:user, name: 'Billy Bob')
|
||||
updater = described_class.new(acting_user, user)
|
||||
updater = UserUpdater.new(acting_user, user)
|
||||
|
||||
updater.update(name: 'Jim Tom')
|
||||
|
||||
expect(user.reload.name).to eq 'Jim Tom'
|
||||
end
|
||||
|
||||
it 'updates bio' do
|
||||
it 'updates various fields' do
|
||||
user = Fabricate(:user)
|
||||
updater = described_class.new(acting_user, user)
|
||||
updater = UserUpdater.new(acting_user, user)
|
||||
|
||||
updater.update(bio_raw: 'my new bio')
|
||||
updater.update(bio_raw: 'my new bio',
|
||||
email_always: 'true',
|
||||
mailing_list_mode: true,
|
||||
digest_after_days: "8")
|
||||
user.reload
|
||||
|
||||
expect(user.reload.user_profile.bio_raw).to eq 'my new bio'
|
||||
expect(user.user_profile.bio_raw).to eq 'my new bio'
|
||||
expect(user.user_option.email_always).to eq true
|
||||
expect(user.user_option.mailing_list_mode).to eq true
|
||||
expect(user.user_option.digest_after_days).to eq 8
|
||||
end
|
||||
|
||||
context 'when update succeeds' do
|
||||
it 'returns true' do
|
||||
user = Fabricate(:user)
|
||||
updater = described_class.new(acting_user, user)
|
||||
updater = UserUpdater.new(acting_user, user)
|
||||
|
||||
expect(updater.update).to be_truthy
|
||||
end
|
||||
|
@ -61,7 +68,7 @@ describe UserUpdater do
|
|||
it 'returns false' do
|
||||
user = Fabricate(:user)
|
||||
user.stubs(save: false)
|
||||
updater = described_class.new(acting_user, user)
|
||||
updater = UserUpdater.new(acting_user, user)
|
||||
|
||||
expect(updater.update).to be_falsey
|
||||
end
|
||||
|
@ -73,7 +80,7 @@ describe UserUpdater do
|
|||
guardian = stub
|
||||
guardian.stubs(:can_grant_title?).with(user).returns(true)
|
||||
Guardian.stubs(:new).with(acting_user).returns(guardian)
|
||||
updater = described_class.new(acting_user, user)
|
||||
updater = UserUpdater.new(acting_user, user)
|
||||
|
||||
updater.update(title: 'Minion')
|
||||
|
||||
|
|
Loading…
Reference in New Issue