-
-
Notifications
You must be signed in to change notification settings - Fork 199
feat: add checkboxes for how you found us options during onboarding #2303
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
base: master
Are you sure you want to change the base?
feat: add checkboxes for how you found us options during onboarding #2303
Conversation
720d71f
to
4af4d4f
Compare
Add spacing around how you found us section
Move validation from model to controller so validation doesn't block new user creation and is only valid for the member details page.
Fix failing tests and move other_reason into member params and give param name more description
4af4d4f
to
73f9c9e
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.
I made invidividual comments about details, mostly about Parameters.
@@ -0,0 +1,84 @@ | |||
RSpec.describe Member::DetailsController, type: :controller 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.
Minor: type metadata for tests is derived from directory, omit it, for clarity.
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.
done
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.
This is ready to go, 🐱, and when Rails 7.1 is in prod, we should merge this.
@olleolleolle @davidmillen50 can I give some feedback on this one before it gets merged in please? 🙏🏻 |
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.
Hi David!
Before diving into specific suggestions of code changes here the first thing is a couple of suggestion around the data model that might simplify things and make the data easier to analyse in the future.
The first is to separate the option strings displayed to the user from the values in the database. e.g. to display as "Search engine (Google etc.)" but to store as an enum value such as search_engine
. This means if we want to change the text displayed to the user in the future we don't end up with slightly different strings in the database corresponding to effectively the same answer.
I would also consider storing the "other" option into its own separate database field rather than combining it into a single list with the standard options. This has the benefit from the data side in that the array contains only standard values and custom values are kept separate, and it should also simplify the controller code and remove the need for a lot of the custom logic there.
Also, although Kimberley's original issue for this mentioned check box options it could be worth asking her if we definitely want the user to be able to select multiple options, or if this should be a single choice via radio buttons/dropdown list instead? While it's technically possible for a member to have heard about codebar through multiple routes, maybe what we're really interested in is just the one that prompted them to actually sign up?
Hope this is useful. And if you decide to make some of the controller/view changes and would like a hand then just let me know.
Cheers
flash[notice] = I18n.t('notifications.signing_up') | ||
@member.newsletter ||= true | ||
end | ||
|
||
def update | ||
return render :edit unless @member.update(member_params) | ||
how_found = Array(member_params[:how_you_found_us]).reject(&: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.
I think all of the logic here should be moveable to a combination of the member_params
method and validation on the model such that the controller action can stay as a simple @member.update(member_params)
For instance the handling of Rails' blank check box can be abstracted away into member_params
.
I'll write a general comment as part of this review with a couple of thoughts and suggestions on the data model used, and if applying those suggestions it will hopefully simplify the update
action.
I can see that it makes things trickier if you're wanting to require "how found" here, but not on other updates to a member (e.g. when an existing member updates their own profile). However, I think it would be good to have a look at the other suggestions I'll make and then see how this is looking. But one option would be to have an "unknown" value rather than blank for existing members and then the validation can live on the model.
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've refactored the controller to move some of the logic to the concern. Moving the validation to the model will block any instances where a user is created or edited which aren't the onboarding page or the edit profile page.
.col-12.mb-3 | ||
%label{ for: 'how_you_found_us' }= t('member.details.edit.how_you_found_us') | ||
%span * | ||
- options = ['From a friend', 'Search engine (Google etc.)', 'Social Media', "One of Codebar's hosts or partners"] |
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 this list of standard options should be pulled out into a constant rather than living in the view here.
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.
done
@@ -15,6 +15,18 @@ | |||
= f.input :about_you, as: :text, label: t('member.details.edit.coach.about_you'), input_html: { rows: 3 }, required: true | |||
- else | |||
= f.input :about_you, as: :text, label: t('member.details.edit.student.about_you'), input_html: { rows: 3 }, required: true | |||
- if @member.errors[:how_you_found_us]&.any? |
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 this should be simplifiable into two f.input
lines: one for the checkboxes and one for the "other" text field.
Simple Form can take care of displaying the labels for each check box value and for displaying any validation errors for the fields.
Simple Form detects that an attribute on the model is an array so you should just need to provide the collection of allowed values and the indication of whether to use check boxes vs. radio buttons.
Something like:
f.input :how_you_found_us, collection: <a constant for the list of options>, as: :check_boxes
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.
(Typo: inout
-> input
.)
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've implemented this for the most part.
= check_box_tag 'member[how_you_found_us][]', option, false, id: "how_you_found_us_#{option.parameterize}", class: 'form-check-input' | ||
= label_tag "how_you_found_us_#{option.parameterize}", option, class: 'form-check-label', style: 'margin-left: 8px;' | ||
= label_tag :how_you_found_us_other_reason, t('member.details.edit.how_you_found_us_other_reason'), class: 'my-1' | ||
= text_field_tag 'member[how_you_found_us_other_reason]', nil, placeholder: "Please specify how you heard about us", class: 'form-control w-100' |
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.
Once using Simple Form f.input
for the field the placeholder text can be moved to en.yml
and will be picked up automatically.
@KimberleyCook do you have a preference for radio buttons or check boxes? |
Move options consolidation to member concern and refactor view to use f.input for checkboxes and 'other' text field
@davidmillen50 I think I want users to only be able to choose one option, as @mikej said I am really interested in the option that made them sign up |
@@ -1,6 +1,13 @@ | |||
class Member < ApplicationRecord | |||
include Permissions | |||
|
|||
HOW_YOU_FOUND_US_OPTIONS = [ | |||
'From a friend', |
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 it would still be worthwhile these being enum
-style values rather than the label text. So e.g. social_media
, host_or_partner
etc.
When using f.input
for the collection you can pass a label_method
that controls how the values are turned into the actual text to display to the user. e.g. to look this up at i18n strings:
label_method: ->(option) { t("found_us.#{foption}") }
Thanks for making some of the changes here. I've just added a follow up comment about how we might still use enum values. When you get the chance, would you like to take a look at switching this over to just choosing a single option and then we can take a another look at how this is looking overall? Thanks |
Add a column to member table called how_you_found_us and is populated with an array depending on options selected. How you found us is a mandatory field on the onboarding page and if not added then warning text will appear. Adding the 'how you found us' reason to a user's profile will follow in another PR.
Making the 'other' option a checkbox that reveals a text input would likely require some bespoke javascript code as simple forms don't allow that. I have therefore just left the text field visible and removed the 'other' option so the implementation is kept simple.
The options selected including the other text field are saved into the db in the members table under the
how_you_found_us
column as an array.The below red message appears if you try to click next without selecting a reason