New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Subscribe the newsletter if email_newsletter is changed #14226
Subscribe the newsletter if email_newsletter is changed #14226
Conversation
|
Thank you for opening this PR! We appreciate you! For all pull requests coming from third-party forks we will need to A Forem Team member will review this contribution and get back to |
|
|
||
| it "enqueues SubscribeToMailchimpNewsletterWorker when updating email_newsletter to false" do | ||
| notification_setting.update(email_newsletter: true) | ||
| sidekiq_assert_enqueued_jobs(1, only: Users::SubscribeToMailchimpNewsletterWorker) do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used not sidekiq_assert_enqueued_with but sidekiq_assert_enqueued_jobs for checking the jobs count. Because L24 pushes a Users::SubscribeToMailchimpNewsletterWorker job as well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great job, @takmar! 🚀
Just a few small changes requested.
| @@ -13,7 +13,8 @@ class NotificationSetting < ApplicationRecord | |||
| after_commit :subscribe_to_mailchimp_newsletter | |||
|
|
|||
| def subscribe_to_mailchimp_newsletter | |||
| return unless email_newsletter | |||
| return if Settings::General.mailchimp_api_key.blank? | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@takmar This is an amazing catch Takmar, thank you so much! 🙏🏾
| let!(:user) { create(:user) } | ||
| let(:notification_setting) { described_class.find_by(user_id: user.id) } | ||
|
|
||
| describe "validations" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm tagging @citizen428 and @rhymes to get their take on this, @takmar, but I believe we can remove this entire describe block, and the corresponding solitary validation in app/models/users/notification_setting.rb:7 (line 7).
When running the spec, I get the following warning from shoulda-matchers gem:
Warning from shoulda-matchers:
You are using `validate_inclusion_of` to assert that a boolean column
allows boolean values and disallows non-boolean ones. Be aware that it
is not possible to fully test this, as boolean columns will
automatically convert non-boolean values to boolean ones. Hence, you
should consider removing this test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can remove this, see http://www.chrisrolle.com/en/blog/boolean-attribute-validation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I removed the code related to validation. Thank you!
93095a3
| let!(:user) { create(:user) } | ||
| let(:notification_setting) { described_class.find_by(user_id: user.id) } | ||
|
|
||
| describe "validations" do |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we can remove this, see http://www.chrisrolle.com/en/blog/boolean-attribute-validation.
|
I've noticed that the email column is nullable, so I also added the line to check an email existence to avoid enqueuing a job to subscribe to the newsletter without an email. |
|
@takmar thanks for the changes! Looks like there are two legit failures in the tests here https://app.travis-ci.com/github/forem/forem/jobs/524379134#L913-L914 Can you take a look? |
|
@rhymes The reason for both of the test failures is that the controller subjected to testing raised the ActiveRecord::NotNullViolation error when those tests set nil to the non-nullable email_digest_periodic column. This is because of the removal of the validation for email_digest_periodic. Though the failure tests expected the controller to set an error message in case of validation failure, there are no longer validations on the model. So we can not test that case anymore. I established the following ways to manage the failures:
Though I removed the validation showing the warning, Rails Guides introduce another way to validate a boolean column. When I tried to implement a validation this way and added the test for it with the validate_exclusion_of matcher, the warnings no longer appeared. This will prevent unexpectedly raising the error and set an error message to a model instance, so I think this could be a better way to deal with the failures. What do you think about these? Or do you have any other ideas? |
@takmar Wouldn't |
|
@citizen428 https://github.com/rails/rails/blob/main/activemodel/lib/active_model/validations/presence.rb#L5-L8 |
|
Yup @takmar, my bad, I didn't properly take the context of our discussion (booleans) into account 🤦♂️ 😃 I'm personally of the opinion that boolean columns should always be non-nullable dealing with a tri-state is almost never what one wants. |
@citizen428 Let me check if I understood correctly. Does this mean it's better to add a validation to check if nil for a boolean column? |
|
I just meant that boolean columns should pretty much always have a non-null constraint in the DB. Whether or not we put a validation in front of that depends a lot on where/how a value is used, i.e. how important it is to communicate this back to the user in a friendlier way than an exception. |
|
`It seems we have legitimate spec failures right now. On a similar PR we recently made the call to keep the boolean validation in until we have a more comprehensive strategy across the app. So if you want to re-add it that's fine. |
|
I'm sorry for my late response. I pushed another commit to fix the failures in the tests. I ended up adding validations in the way I described before.
Though I implemented the validations for now, feel free to remove them when you decided on the strategy. |
|
@msarit @citizen428 just a quick ping as the specs are passing now 🙂 |
| @@ -4,7 +4,21 @@ class NotificationSetting < ApplicationRecord | |||
|
|
|||
| belongs_to :user, touch: true | |||
|
|
|||
| validates :email_digest_periodic, inclusion: { in: [true, false] } | |||
| validates :email_badge_notifications, exclusion: [nil] | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still not super convinced by the need for these validations, as we ensure database integrity via non-null constraints and the UI should never generate a nil here. But as you said, we can decide on this later, it's ok to leave it in for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the UI should never generate a nil here.
When I read this, I have finally understood what I felt something wrong.
I was guessing these sending nil tests below(previously failed tests in this PR) are for a case that a user sends nil deliberately by rewriting HTML or doing something like that.
forem/spec/requests/user/user_notification_settings_spec.rb
Lines 40 to 44 in 1253d90
| it "returns error message if settings can't be saved" do | |
| put users_notification_settings_path(user.notification_setting.id), | |
| params: { users_notification_setting: { tab: "notifications", email_digest_periodic: nil } } | |
| expect(flash[:error]).not_to be_blank |
forem/spec/requests/user/user_notification_settings_spec.rb
Lines 85 to 91 in 1253d90
| it "returns 422 status and errors if errors occur" do | |
| patch onboarding_notifications_checkbox_update_path(format: :json), | |
| params: { notifications: { tab: "notifications", email_digest_periodic: nil } } | |
| expect(response.status).to eq(422) | |
| expect(response.parsed_body["errors"]).not_to be_blank | |
| end |
As you said, a user never sends nil usually, so I think it would be better to remove these tests.
And do so, we could also remove all the validations on the model.
What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I think this is where we previously didn't quite manage to get on the same page 😃 I always approached this from the point of our UI where this is a checkbox:
The way Rails handles these is via a hidden field with a value of "0", so an unchecked box also won't result in nil.
So yes, I think we can remove these specs and the newly added validations, if someone really manages to send a nil here I'd be ok with the exception from the DB bubbling up because it would truly be an exceptional circumstance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can remove these specs and the newly added validations
I removed the specs and the validations I added.
(I think email_digest_periodic validation is also unnecessary.)
if someone really manages to send a nil here I'd be ok with the exception from the DB bubbling up because it would truly be an exceptional circumstance.
I totally agree with you 👍
6100d9e
to
4fce7d6
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Great work @takmar!

What type of PR is this? (check all applicable)
Description
In
Users::NotificationSettingmodel,Users::SubscribeToMailchimpNewsletterWorkeris executed ONLY the caseemail_newsletteris true. So a user can not unsubscribe from the newsletter by updatingemail_newsletterto false.To fix this, I changed
subscribe_to_mailchimp_newslettermethod to checksaved_changes.key?(:email_newsletter)instead ofemail_newsletter.And I also make it to check
Settings::General.mailchimp_api_key.blank?the same asUsermodel.forem/app/models/user.rb
Lines 509 to 511 in e50db31
Related Tickets & Documents
QA Instructions, Screenshots, Recordings
Please replace this line with instructions on how to test your changes, a note
on the devices and browsers this has been tested on, as well as any relevant
images for UI changes.
UI accessibility concerns?
If your PR includes UI changes, please replace this line with details on how
accessibility is impacted and tested. For more info, check out the
Forem Accessibility Docs.
Added/updated tests?
have not been included
[Forem core team only] How will this change be communicated?
Will this PR introduce a change that impacts Forem members or creators, the
development process, or any of our internal teams? If so, please note how you
will share this change with the people who need to know about it.
Admin Guide, or
Storybook (for Crayons components)
or in a forem.dev post
replace this line with details on why this change doesn't need to be
shared
[optional] Are there any post deployment tasks we need to perform?
[optional] What gif best describes this PR or how it makes you feel?