Rails 5: validation of acceptance for a checkbox - ruby-on-rails

I have a sign-up form with some nested fields, and inside this form I have added a checkbox for the terms of service.
I'm trying to validate when the checkbox is checked or not and return an error if not.
validates_acceptance_of :agreement, :allow_nil => true, :accept => true, :on => :create
I do have a boolean column that is set to default inside the accounts table.
add_column :accounts, :agreement, :boolean, default: false
Also, I have added the :agreement to the permitted controller params.
This is the form:
<%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<div class="centerList">
<div id="error_explanation">
<%= devise_error_messages! %></div>
</div>
<div class="form-group">
<span class="asterisk_input"></span>
<%= f.email_field :email, autofocus: true, placeholder: "email", :class=>"form-control" %>
</div>
<div class="form-group">
<span class="asterisk_input"></span>
<%= f.password_field :password, placeholder: "password", autocomplete: "off", :class=>"form-control" %>
</div>
<div class="form-group">
<span class="asterisk_input"></span>
<%= f.password_field :password_confirmation, placeholder: "confirm password", autocomplete: "off", :class=>"form-control" %>
</div>
<%= f.fields_for :account do |form| %>
<div class="form-group">
<span class="asterisk_input"></span>
<%= form.text_field :street, placeholder: "street", :class=>"form-control" %>
</div>
<div class="form-group">
<span class="asterisk_input"></span>
<%= form.text_field :city, placeholder: "city", :class=>"form-control" %>
</div>
<div class="form-group">
<span class="asterisk_input"></span>
<%= form.text_field :state, placeholder: "state", :class=>"form-control" %>
</div>
<div class="form-group">
<span class="asterisk_input"></span>
<%= form.text_field :zip_code, placeholder: "zip code", :class=>"form-control" %>
</div>
<div class="form-group">
<span class="asterisk_input"></span>
<%= form.country_select :country, ["US"], {}, { :class => "form-control", :id=>"sign-frm-input" } %>
</div>
<div class="form-group">
<%= form.check_box :agreement %> I agree to the <%= link_to 'Terms', term_path(:id=>1) %>.
</div>
<% end %>
<div class="form-group">
<%= f.submit "Sign up", :class=>'btn btn-primary' %>
<% end %>
But it returns the form error agreement must be accepted even if I do accept it. Any ideas what I might be missing ohere!

Try: validates :agreement, acceptance: {accept: true} , on: :create,
allow_nil: false
You don't want to :allow_nil => true if you're validating for acceptance.

You can change your model validations and test it.
validates :agreement, inclusion: {in: [true]}
or you can use other validation
validates :agreement, acceptance: { accept: true }

Related

Ruby on rails Active Storage Validations not working

I am using:
Rails 6.0.4.4
Ruby 3.0.0
I have added gem'active_storage_validations' to my project, and am trying to use it to validate that attached avatars are images
class User < ApplicationRecord
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :validatable, :confirmable, :trackable, :lockable, :masqueradable
validates :first_name, :last_name, presence: true
validates :email, uniqueness: true
validates :terms_and_conditions, acceptance: true
validates :avatar, attached: true, content_type: ['image/png', 'image/jpg', 'image/jpeg']
has_one_attached :avatar
end
in my sign_up form
<%= render "devise/shared/error_messages", resource: resource %>
<div class="container pt-3 pb-3">
<div class="card">
<div class="card-header">
<h2>Sign up</h2>
</div>
<div class="card-body">
<%= simple_form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
<div class="field mb-3">
<%= f.label :profile_picture %><br />
<%= f.file_field :avatar, class: "form-control" %>
</div>
<div class="field mb-3">
<%= f.label :email %><br />
<%= f.email_field :email, autofocus: true, autocomplete: "email", class: "form-control", placeholder: "name#email.com" %>
</div>
<div class="field mb-3">
<%= f.label :first_name %><br />
<%= f.text_field :first_name, required: true, autofocus: true, autocomplete: "first_name", class: "form-control" %>
</div>
<div class="field mb-3">
<%= f.label :last_name %><br />
<%= f.text_field :last_name, autofocus: true, autocomplete: "last_name", class: "form-control" %>
</div>
<div class="field mb-3">
<%= f.label :password %>
<% if #minimum_password_length %>
<em>(<%= #minimum_password_length %> characters minimum)</em>
<% end %><br />
<%= f.password_field :password, autocomplete: "new-password", class: "form-control" %>
</div>
<div class="field mb-3">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation, autocomplete: "new-password", class: "form-control" %>
</div>
<div class="form-check form-switch text-muted">
<%= f.check_box :terms_and_conditions, class: 'form-check-input', id: 'flexSwitchCheckDefault' %>
I hereby confirm I have read and undertood the terms and conditions
</div>
<div class="actions">
<%= f.submit "Continue", class: "btn btn-primary" %>
</div>
<% end %>
<br>
<%= render "devise/shared/links" %>
</div>
</div>
</div>
All the other validations work fine.
If I add validations for file type or size on the attached image, it still allows the user to upload any file type and size

Splitting devise edit form to multiple pages

I’m trying to split my rails devise edit form into 3 pages. But when I hit the submit button nothing happens and nothing gets saved. I have a very long sign up process, so that's why, I want to split the edit page.
Any help would be much appreciated.
This is from the log, when I hit the submit button
Started PATCH "/userprofiles/clinic_info" for ::1 at 2020-02-21 08:16:13 +0100
Processing by UserprofilesController#update as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"fYdVH9aY3XfQ+Fu639zhEsvrxRwYtIeYacqrKowDDlPu3r6iuXZOalFahSJ61peVBawf0DioVu+arrJzJK5M9A==", "user"=>{"clinic_name"=>"Kaspers Zoness", "clinic_address"=>"Krebsen 99", "clinic_zip_code"=>"5700", "clinic_city"=>"Svendborg", "clinic_municipality"=>"Svendborg", "clinic_about"=>"Jeg trykker på fødderne", "clinic_mail"=>"kasper#betterwing.dk", "clinic_phone"=>"24210886", "clinic_website"=>""}, "commit"=>"Gem"}
No template found for UserprofilesController#update, rendering head :no_content
Completed 204 No Content in 65ms (ActiveRecord: 0.0ms)
I have created 3 edit pages in this folder views/userprofiles
user_info.html.erb
clinic_info.html.erb
practitioner_info.html.erb
In my routes I have created these routes for the new files and for the update
get "userprofiles/user_info" => "userprofiles#user_info", as: "user_info"
get "userprofiles/clinic_info" => "userprofiles#clinic_info", as: "clinic_info"
get "userprofiles/practitioner_info" => "userprofiles#practitioner_info", as: "practitioner_info"
patch "userprofiles/user_info" => "userprofiles#update"
patch "userprofiles/clinic_info" => "userprofiles#update"
patch "userprofiles/practitioner_info" => "userprofiles#update"
I’ve created this new controller for the purpose
class UserprofilesController < ApplicationController
# fill the methods as you need, you can always get the user using current_user
def user_info
end
def clinic_info
end
def practitioner_info
end
def update
end
end
This is my form for the clinic_info page
<div class="content clinic">
<h2 class="page-title">Generel information</h2>
<div class="basic-section">
<%= form_for(current_user, url: clinic_info_path) do |f| %>
<div class="field text-field">
<%= f.text_field :clinic_name, autofocus: true, autocomplete: "Klinikkens navn", placeholder: "Klinikkens navn" %>
</div>
<div class="field text-field">
<%= f.text_field :clinic_address, autofocus: true, autocomplete: "Adresse", placeholder: "Adresse" %>
</div>
<div class="field-group location-group">
<div class="field text-field">
<%= f.text_field :clinic_zip_code, autofocus: true, autocomplete: "Postnr.", placeholder: "Postnr." %>
</div>
<div class="field text-field">
<%= f.text_field :clinic_city, autofocus: true, autocomplete: "By", placeholder: "By" %>
</div>
<div class="field text-field">
<%= f.text_field :clinic_municipality, autofocus: true, autocomplete: "Kommune", placeholder: "Kommune" %>
</div>
</div>
</div>
<div class="about-section">
<div class="field text-field">
<%= f.text_field :clinic_about, :as => :text, :input_html => { 'rows' => 5}, autofocus: true, autocomplete: "Om klinikken", placeholder: "Om klinikken" %>
</div>
</div>
<div class="field-group contact-section">
<div class="field text-field">
<%= f.text_field :clinic_mail, input_html: { autocomplete: 'email' }, autofocus: true, placeholder: "E-mail" %>
</div>
<div class="field text-field">
<%= f.text_field :clinic_phone, autofocus: true, autocomplete: "Tlf. nr.", placeholder: "Tlf. nr." %>
</div>
<div class="field text-field">
<%= f.text_field :clinic_website, autofocus: true, autocomplete: "Hjemmeside", placeholder: "Hjemmeside" %>
</div>
</div>
<div class="btn-container">
<%= f.submit "Save", :class => 'btn blue' %>
</div>
<% end %>
</div>
Your update method in the UserprofilesController doesn't do anything.
It receives the params from the form that is submitted, but you also need to write code to do something with it(updating the user_profile).
It would look something like:
def update
if current_user.update(user_params)
redirect_to #some_path_here
else
#do something else if it fails
end
end
Then you also need to define the user_params in a private section like:
def user_params
params.require(:user).permit(:clinic_name, :clinic_address, #etc)
end

I need to create two objects in same form (rails)

so please imagine a form for a car reservation, the form contains both some client information(name, age, city..) and also the reservation informations(start_date, end_date...).
So obviously, i need to create in the same form a client first, based on the informations and then the reservation which is related to the created client:
class Client < ActiveRecord::Base
has_many :reservations
end
.
class Reservation < ActiveRecord::Base
belongs_to :client
belongs_to :voiture
end
Here is what i did until now(bad way).
The reservation informations start with f.text_field, and the client informations only with text_field(very bad way yes :( )
<%= form_for([#voiture, #voiture.reservations.new]) do |f| %>
<div class="row">
<div class="col-md-12 price_tag">
<span><%= #voiture.price %>Dhs</span>
<span class="pull-right">Par jour</span>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>Nom</label>
<%= text_field :nom, readonly: 'true', placeholder: 'Nom', class: 'form-control' %>
</div>
<div class="col-md-6">
<label>Prenom</label>
<%= text_field :prenom, readonly: 'true', placeholder: 'Prenom', class: 'form-control', disabled: 'true' %>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>CIN</label>
<%= text_field :cin, readonly: 'true', placeholder: 'CIN', class: 'form-control' %>
</div>
<div class="col-md-6">
<label>Age</label>
<%= text_field :age, readonly: 'true', placeholder: 'Age', class: 'form-control', disabled: 'true' %>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>Ville</label>
<%= text_field :ville, readonly: 'true', placeholder: 'Ville', class: 'form-control' %>
</div>
<div class="col-md-6">
<label>Télephone</label>
<%= text_field :telephone, readonly: 'true', placeholder: 'Telephone', class: 'form-control', disabled: 'true' %>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>Email</label>
<%= text_field :email, readonly: 'true', placeholder: 'Email', class: 'form-control' %>
</div>
</div>
<div class="row">
<div class="col-md-6">
<label>Check In</label>
<%= f.text_field :start_date, readonly: 'true', placeholder: 'Start Date', class: 'form-control' %>
</div>
<div class="col-md-6">
<label>Check Out</label>
<%= f.text_field :end_date, readonly: 'true', placeholder: 'End Date', class: 'form-control', disabled: 'true' %>
</div>
</div>
<%= f.hidden_field :voiture_id, value: #voiture.id %>
<%= f.hidden_field :prix, value: #voiture.prix %>
<%= f.hidden_field :total, id: 'reservation_total' %>
<%= f.submit "Book Now", id:"btn_book", class: "btn btn-primary wide", disabled: 'true' %>
Controller :
class ReservationsController < ApplicationController
before_action :authenticate_user!
def create
#client = Client.create(client_params)
#reservation = #client.reservations.create(reservation_params)
redirect_to #reservation.voiture, notice: "Votre reservation a bien ete cree"
end
def reservation_params
params.require(:reservation).permit(:start_date, :end_date, :prix, :total, :voiture_id)
end
def client_params
params.permit(:nom, :prenom, :cin, :age, :ville, :telephone, :email)
end
end
I'm sure there is a good and clean way to do that..
Thanks !
I would look at nested attributes for a good clean solution, here is the doc link http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
There is also a gem that can simplify it for you
https://github.com/ryanb/nested_form

Nomethoderror on form using mail_form gem for second form

i am building a website for which i already made a working contact form using the mail_form gem. But now i wan't to create another form somewhere on the website, also using the mail_form gem.
I made a new controller, a new model, new views and put up the routes.
boosts_controller.rb
class BoostsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact = Contact.new(params[:boost])
#contact.request = request
if #contact.deliver
flash.now[:notice] = "Thank you very much, we will contact you on your email with further instructions"
else
flash.now[:error] = "Something went wrong, please try again."
render :new
end
end
end
Model: boost.rb
class Boost < MailForm::Base
attribute :paypal_transaction_reference, :validate => true
attribute :email, :validate => /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\z/i
attribute :message
attribute :account_name, :validate => true
attribute :account_password, :validate => true
attribute :account_password_confirmation, :validate => true
attribute :nickname, :captcha => true
# Declare the e-mail headers. It accepts anything the mail method
# in ActionMailer accepts.
def headers
{
:subject => "Form",
:to => "xxxx#hotmail.com, xxxx#gmail.com",
:from => %("#{account_name}", <#{email}>)
}
end
end
boosts/new.html.erb
<div class="col-md-12 text-center">
<div class="sign-box">
<header class="sign-title"> form</header>
<%= form_for #boost do |f| %>
<div class="field form-group">
<%= f.label :paypal_transaction_reference, class: 'float-left' %>
<%= f.text_field :paypal_transaction_reference, required: true, class: 'form-control', autofocus: true %>
</div>
<div class="field form-group">
<%= f.label :email, class: 'float-left' %>
<%= f.email_field :email, class: 'form-control', required: true, autocomplete: "off" %>
</div>
<div class="field form-group">
<%= f.label :account_name, class: 'float-left' %>
<%= f.text_field :account_name, class: 'form-control', required: true, autocomplete: "off" %>
</div>
<div class="field form-group">
<%= f.label :account_password, class: 'float-left' %>
<%= f.password_field :account_password, class: 'form-control',required: true, autocomplete: "off" %>
</div>
<div class="field form-group">
<%= f.label :account_password_confirmation, class: 'float-left' %>
<%= f.password_field :account_password_confirmation, class: 'form-control', required: true, autocomplete: "off" %>
</div>
<div class="field form-group">
<%= f.label :message, class: 'float-left' %>
<%= f.text_area :message, as: :text, class: 'form-control', autocomplete: "off" %>
</div>
<div class="hidden">
<%= f.label :nickname %>
<%= f.text_field :nickname, hint: 'leave this field blank' %>
</div>
<%= f.submit 'Send', class: 'btn btn-rounded' %>
<% end %>
</div>
</div>
routes.rb from the working contact form plus the new one.
match '/boosts', to: 'boosts#new', via: 'get'
resources :boosts, only: [:new, :create]
match '/contacts', to: 'contacts#new', via: 'get'
resources :contacts, only: [:new, :create]
The error i get on localhost is:
undefined method `paypal_transaction_reference' for #<Contact:0x007f9dbbb307d0>
The error log
Completed 500 Internal Server Error in 31ms (ActiveRecord: 0.0ms)
ActionView::Template::Error (undefined method `paypal_transaction_reference' for #<Contact:0x007f9dbbb307d0>):
6:
7: <div class="field form-group">
8: <%= f.label :paypal_transaction_reference, class: 'float-left' %>
9: <%= f.text_field :paypal_transaction_reference, required: true, class: 'form-control', autofocus: true %>
10: </div>
11:
12: <div class="field form-group">
app/views/boosts/new.html.erb:9:in `block in _app_views_boosts_new_html_erb___4155220419788953995_70157717804640'
app/views/boosts/new.html.erb:5:in `_app_views_boosts_new_html_erb___4155220419788953995_70157717804640'
IN Boost Controller
#contact = Contact.new
Should be
#boost = Boost.new

Triple nested attributes in ruby. Not sure if I am setting them up right or if they can be done. Ruby

I have a triple nested attributes that I am trying to capture all the information for in one form. In short I have an event that has many event_locations which have many event_dates which have many event_roles. I have the form in my event new. I think the issues is in my events model and I need to say that there is going other "accepts_nested_attributes_for" for event_dates and event_roles because right now in the event_params I do get the event and event_location information.
events controller
def create
#event = Event.new(event_params)
if #event.save
redirect_to #event, notice: 'Event was successfully created.'
else
render :new
end
end
private
def event_params
params.require(:event).permit(:name, :event_details, event_locations_attributes: [:label, :address, :zip, :state, :country, :notes], event_dates_attributes: [:event_date, :start_time, :end_time], event_roles_attributes: [:type, :hourly_rate, :quantity])
end
event.rb
class Event < ActiveRecord::Base
has_many :event_locations, :dependent => :destroy
has_many :event_dates, through: :event_locations
belongs_to :agency
accepts_nested_attributes_for :event_locations, :allow_destroy => true
end
event new
<h3> New Event </h3>
<%= form_for #event do |f| %>
<%= f.text_field :name, :required => true, placeholder: "Name", :maxlength => 200, class: "form-control title_input_field" %><br>
<%= f.text_area :event_details, :required => true, placeholder: "What are some of the event details", size: "100x10", class: "input_field2" %> <br>
<h3> Event Locations </h3>
<%= f.fields_for :event_locations do |builder| %>
<%= render "location_fields", :f => builder %>
<% end %>
<%= f.submit "Create!", :class => 'submit_button' %>
<% end %>
_location_fields.html.erb
<p>
<div class="row">
<div class="col-sm-5">
<%= f.text_field :label, :required => true, placeholder: "Label", :maxlength => 1000, class: "form-control title_input_field" %><br>
</div>
<div class="col-sm-5">
<%= f.text_area :notes, :required => true, placeholder: "Notes", :maxlength => 200, class: "form-control title_input_field" %><br>
</div>
</div>
<div class="row">
<div class="col-sm-5">
<%= f.text_field :address, :required => true, placeholder: "Address", :maxlength => 200, class: "form-control title_input_field" %><br>
</div>
<div class="col-sm-2">
<%= f.text_field :state, :required => true, placeholder: "State / Provience", :maxlength => 200, class: "form-control title_input_field" %><br>
</div>
<div class="col-sm-2">
<%= f.text_field :country, :required => true, placeholder: "Country", :maxlength => 200, class: "form-control title_input_field" %><br>
</div>
<div class="col-sm-2">
<%= f.text_field :zip, :required => true, placeholder: "Zip Code", :maxlength => 200, class: "form-control title_input_field" %><br>
</div>
</div>
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Location" %>
</p>
<%= f.fields_for :event_date do |builder| %>
<%= render "event_date_fields", :f => builder %>
<% end %>
--
_event_date_fields.html.erb
<p>
<h3> Event Date </h3>
<div class="row">
<div class="col-sm-3">
<div class="form-group">
<div class='input-group date' id='datetimepicker1' />
<%= f.text_field :event_date, placeholder: "Select Event Date", class: "form-control", type:'text' %>
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div> <!-- date -->
</div> <!-- form-group -->
</div>
<div id="datepairExample">
<div class="col-sm-4">
<%= f.text_field :start_time, placeholder: "Start Time", class: 'time start form-control' %>
</div>
<div class="col-sm-1">to</div>
<div class="col-sm-4">
<%= f.text_field :end_time, placeholder: "End Time", class: 'time end form-control' %>
</div>
</div>
</div>
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remove Date" %>
</p>
<%= f.fields_for :event_role do |builder| %>
<%= render "event_role_fields", :f => builder %>
<% end %>
In short, you need to allow all the models to allow nested attributes for their direct associations, so:
class Event < ActiveRecord::Base
has_many :event_locations, :dependent => :destroy
accepts_nested_attributes_for :event_locations, :allow_destroy => true
class EventLocation < ActiveRecord::Base
has_one :event_date
accepts_nested_attributes_for :event_date, allow_destroy: true
class EventDate < ActiveRecord::Base
has_one :event_role
accepts_nested_attributes_for :event_role, allow_destroy: true
Then your strong params should look like this:
params.require(:event).permit(:name, :event_details,
event_locations_attributes: [:label, :address, :zip, :state, :country, :notes,
event_date_attributes: [:event_date, :start_time, :end_time,
event_role_attributes: [:type, :hourly_rate, :quantity]]])

Resources