0

I need to add required fields for some forms on my website in order to better verify users

My intended solve: In looking online, I’ve tried a simple html fix within views>devise>registrations>new.html.erb and have started by editing the following code:

<div class="flex-col md:flex md:flex-row">
      <div class="form-group mb-3 pr-0 md:pr-2">
       <%= f.label :first_name %>
       <%= f.text_field :first_name, autofocus: true, autocomplete: "given-name", class: "form-control"%>
      </div>

I've attempted to implement the following: :required => :true , required: true , validates :first_name, presence => true and other similar variations

I also tried changing in the simple_form.rb file: config.browser_validations = false to = true in order to enable validations on form fields. Where I became stuck: None of these changes have broken the localhost, but also haven't changed anything. Each new account creation/sign up is able to be executed without entering a First Name. I can't tell if it's simpleform, html or otherwise. Here's a few links I've tried to follow:

How to make a field required in Rails?

https://guides.rubyonrails.org/v3.2.13/active_record_validations_callbacks.html

Rails: Attribute required for collection in simple_form https://github.com/heartcombo/simple_form (README)

HTML5 'required' validation in Ruby on Rails forms

EDIT: User.rb as requested:

class User < ApplicationRecord
  # acts_as_token_authenticatable

  rolify
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable, :recoverable,
         :trackable, :validatable, :rememberable, :confirmable, :async
  # :omniauthable, omniauth_providers: %i[facebook]
  mount_uploader :logo, AvatarUploader

  attr_accessor :skip_password_validation, :registered_as

  has_many :wishlists
  has_many :projects, dependent: :destroy

  # callbacks
  after_create :assign_role
  after_save :sync_to_active_campaign_contact

  #
  def already_wishlist?(project)
    Wishlist.where(user_id: id, project_id: project.id).exists?
  end

  #
  # def self.from_omniauth(auth)
  #   where(provider: auth.provider, uid: auth.uid).first
  #   # where(provider: auth.provider, uid: auth.uid).first_or_create do |user|
  #   #   user.email = auth.info.email
  #   #   user.skip_password_validation = true
  #   #   # user.password = Devise.friendly_token[0,20]
  #   #   # user.name = auth.info.name   # assuming the user model has a name
  #   #   # user.image = auth.info.image # assuming the user model has an image
  #   #   # If you are using confirmable and the provider(s) you use validate emails,
  #   #   # uncomment the line below to skip the confirmation emails.
  #   #   # user.skip_confirmation!
  #   # end
  # end

  # after_create :send_admin_mail
  # def send_admin_mail
  # ###Send email stuff here
  # end

  #
  def sync_to_active_campaign_contact
    return if Rails.env.development?
    if (confirmed_at.nil? ? false : confirmed_at <= Time.zone.now)

      begin
        fields = {
          'email' => email
        }

        ac_tags = ActiveCampaign.show_tags
        contact_tags = []
        if has_role?(:buyer)
          ac_fields = ActiveCampaign.show_fields
          field_id = ac_fields[:fields].find { |field| field[:title].casecmp?('buyer type') }[:id]
          fields.merge!({ fieldValues: [{
                          field: field_id,
                          value: buyer_type
                        }] }, first_name: first_name, last_name: last_name)
          contact_tags << { contact: "id", tag: ac_tags[:tags].find { |tag| tag[:tag].casecmp?('buyer') }[:id] }
          contact_tags << { contact: "id", tag: ac_tags[:tags].find { |tag| tag[:tag].casecmp?(buyer_type) }[:id] }
        end
        # 1 user can have both roles, using else would crash the logic
        if has_role?(:developer)
          fields.merge!('orgname' => business_name)
          contact_tags << { contact: "id", tag: ac_tags[:tags].find { |tag| tag[:tag].casecmp?('developer') }[:id] }
        end

        ac_contact = ActiveCampaign.sync_contact(fields)
        ac_contact_id = ac_contact.dig(:contact, :id)

        contact_tags.each do |ct|
          contact_tag = ct.merge({ contact: ac_contact_id, tag: ct[:tag] })
          ActiveCampaign.create_contact_tag(contact_tag)
        end
      rescue StandardError
        logger.debug 'unable to sync with active campaign'
      end
    end
  end

  protected

  #
  def password_required?
    return false if skip_password_validation

    super
  end

  #
  def assign_role
    add_role registered_as
  end
end

EDIT 2: I'm also needing to include a required selection from an f.select option, while disabling the default 'Select One' option:

<div class="form-group mb-3">
            <%= f.label :buyer_type, "Which best describes you: " %>
            <%= f.select :buyer_type, ['Please Select','Option 1', 'Option 2', 'Option 3'], {}, { class: "form-control" } %>
          </div>
LJ-03
  • 49
  • 9
  • 1
    `required: true` option should be ok, what's the generated HTML? – eux Feb 02 '21 at 06:09
  • @eux Sorry I'm very new to coding in general - what specifically do you need to see? – LJ-03 Feb 02 '21 at 06:19
  • 1
    It's ok, I mean the final HTML for `first_name` field from the browser, similar to ``. – eux Feb 02 '21 at 06:22
  • This validation belongs in the `User` model (or whatever object is `registerable`). https://stackoverflow.com/questions/29772931/how-do-i-validate-certain-fields-with-rails-devise-on-registration-only – engineersmnky Feb 02 '21 at 18:19
  • @engineersmnky Looking in the `User` model, I can see a line with the following: `}] }, first_name: first_name, last_name: last_name)`, what would be the way to change this, if this is the right spot? – LJ-03 Feb 02 '21 at 22:53
  • @eux I believe it should be: `` `` I just went 'Inspect Element' on the localhost and found the code corresponding to the first_name input field - I'm assuming that's what you were after? – LJ-03 Feb 02 '21 at 22:56
  • @LJ-03 Yes, that's it, and if you add `required: true` option to `f.text_field` correctly, the `input` tag should have a `required` attribute: ``, then you could check whether you add the option successfully or the browser doesn't work correctly. – eux Feb 03 '21 at 01:11
  • Post your User model by editing the original post – engineersmnky Feb 03 '21 at 01:43
  • @engineersmnky done. @eux good to know! I'm playing around with it now but nothing I'm doing is changing anything! Any ideas on how the `required: true` should be implemented into the `f.text_field`? I'm at a loss! – LJ-03 Feb 03 '21 at 03:03
  • Just add this line `validates :first_name, presence: true`, that you already posted, to the User model – engineersmnky Feb 03 '21 at 03:08
  • Does it matter where it goes? Or rather, where should it go? – LJ-03 Feb 03 '21 at 03:26
  • @engineersmnky it worked!! Thank you so much! Is there a way to also do this for a `f.select` feature? To ensure that one option (and not the 'Please Select' option) is chosen? – LJ-03 Feb 03 '21 at 04:09
  • Edited post again to reflect `f.select` options question – LJ-03 Feb 03 '21 at 04:20
  • Try `f.select :buyer_type, ['Option 1', 'Option 2', 'Option 3'], {prompt: true}, { class: "form-control"} %>` – engineersmnky Feb 04 '21 at 04:36
  • @engineersmnky It didn't break it (hallelujah) but I'm still able to select the 'Please select' option when signing up. – LJ-03 Feb 04 '21 at 04:55
  • Try `f.select :buyer_type, ['Option 1', 'Option 2', 'Option 3'], {include_blank: true}, { class: "form-control", required: 'required'} %>` instead – engineersmnky Feb 04 '21 at 12:22
  • It works! Thank you so so much for this! Feel free to add the answer or I can do this – LJ-03 Feb 05 '21 at 02:18
  • You can post your own answer if you'd like. BTW make sure when responding to comments to tag the User using @username so that the User is notified of your response – engineersmnky Feb 06 '21 at 00:05
  • 1
    Okay, will do! Thanks for that and all your help @engineersmnky – LJ-03 Feb 08 '21 at 03:37

1 Answers1

0

Thanks to @engineersmnky for the answers on this one:

For the f.text_fieldproblem, adding:

validates :first_name, presence: true
validates :last_name, presence: true

to user.rb made my First and Last Name fields mandatory, not altering the html.

For the f.select problem was solved by just adjusting the html!

I've seen multiple fixes on stack overflow that have worked for people, but the one that worked for me was taking this:

<%= f.select :buyer_type, ['Please Select','Option 1', 'Option 2', 'Option 3'], {}, { class: "form-control" } %>

and changing it to this:

<%= f.select :buyer_type, ['Option 1', 'Option 2', 'Option 3'], {include_blank: "Please Select"}, { class: "form-control" , required: 'required'} %>
LJ-03
  • 49
  • 9