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
Related
My profile role is created and when the user logs in the profile controller's edit action view will be displayed. I want to show the role that is assigned to user in the edit action and the user cannot change the role. My edit.html.erb file is given as:
<div class="row">
<div class="col-md-6 offset-md-3">
<h3>Profile</h3>
<%= form_for(#profile) do |f| %>
<div class="form-group">
<%= f.label :first_name %><br />
<%= f.email_field :first_name, autofocus: true, class: "form-control"%>
</div>
<div class="form-group">
<%= f.label :last_name %><br />
<%= f.password_field :last_name, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :role %><br />
<%= f.select(:role, [['User', 'user'], ['Vip', 'vip'], ['Admin', 'admin']]) %>
</div>
<div class="actions form-group">
<%= f.submit "Submit", class: 'btn btn-primary' %>
</div>
<% end %>
</div>
The simplest possible way is just to use String#humanize from ActiveSupport.
Capitalizes the first word, turns underscores into spaces, and (by
default)strips a trailing '_id' if present. Like titleize, this is
meant for creating pretty output.
irb(main):008:0> roles.roles.keys.map(&:humanize)
=> ["User", "Vip", "Admin"]
irb(main):009:0> Profile.new(role: :admin).role.humanize
=> "Admin"
Profile.roles gives us the hash mapping for the Enum.
You can use this to generate the select tag with:
<%= form.select :role, Profile.roles.keys.map{|k| [k.humanize, k] } %>
You can get "vip".humanize to return "VIP" by setting up an inflection:
# config/initializers/inflections.rb
ActiveSupport::Inflector.inflections(:en) do |inflect|
inflect.acronym 'VIP'
end
This may require restarting your Rails server before it kicks in.
Using the I18n module
But if you want a more flexible solution that lets you set the mappings yourself (and works with translations) use the I18n module:
# config/locales/en.yml
en:
activerecord:
attributes:
profile:
roles:
user: 'User'
vip: 'Very Important Person'
admin: 'Admin'
# app/helpers/users_helper.rb
module UsersHelper
def translate_role(role)
I18n.t("activerecord.attributes.user.roles.#{ role }", default: role.humanize)
end
def role_options
Profile.roles.keys.map{|k| [translate_role(k), k] }
end
end
You would then display the users role by:
<%= translate_role(#user.role) %>
And you can setup the form input as:
<%= form.select :role, role_options %>
You can use a helper method, For example in the application_helper.rb you can make a method like this:
class ApplicationHelper
def profile_role(profile)
# Perform your logic
# if you are using as_enum gem for example
Profile.roles.select{|symbol_role,integer_rep| integer_rep == profile.role}.keys.first.to_s
# of course there could be much better way to get the string.
end
end
Then in your view, If user should not be able to change it, there is no need to make it as drop-down list:
<div class="row">
<div class="col-md-6 offset-md-3">
<h3>Profile</h3>
<%= form_for(#profile) do |f| %>
<div class="form-group">
<%= f.label :first_name %><br />
<%= f.email_field :first_name, autofocus: true, class: "form-control"%>
</div>
<div class="form-group">
<%= f.label :last_name %><br />
<%= f.password_field :last_name, class: "form-control" %>
</div>
<div class="form-group">
<%= f.label :role %><br />
<%= text_field_tag 'role', profile_role(#profile), disabled: true %>
</div>
<div class="actions form-group">
<%= f.submit "Submit", class: 'btn btn-primary' %>
</div>
<% end %>
You can just show it as regular text, e.g.:
...
<div class="form-group">
<%= f.label :last_name %><br />
<%= f.password_field :last_name, class: "form-control" %>
</div>
<p>
Role:<br />
<%= #profile.role %>
</div>
<div class="actions form-group">
<%= f.submit "Submit", class: 'btn btn-primary' %>
</div>
...
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 }
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
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
I am working with the mail_form gem. I have already created an specific controller for the contact form and everythink seems right but when I submit any form the view does´nt change from the create one to the create one but the url does. It shows the localhost3000/gmm/contacts(which has changed from localhost3000/gmm/contacts/new). I am worried about this issue; Moreover, the new view shows the e-mail in the name´s field as showed in the image:
"http://2.bp.blogspot.com/-Q4qUs1CHm-M/Voqc-VYiXII/AAAAAAAAAdE/nJMxgpTEu5s/s320/problem1.jpg"
Controller file:
class ContactsController < ApplicationController
def new
#contact = Contact.new
end
def create
#contact=Contact.new(params[:contact])
#contact.request=request
if #contact.deliver
flash.now[:error]=nil
else
flash.now[:error]='Cannot send message.'
render :new
end
end
end
New view:
<body>
<section>
<div class="container">
<div class="row">
<div class="col-lg-8 col-lg-offset-2 text-center">
<h2 class="margin-top-0 wow fadeIn">Get in Touch</h2>
<hr class="primary">
<p>We love feedback. Fill out the form below and we'll get back to you as soon as possible.</p>
</div>
<div class="col-lg-10 col-lg-offset-1 text-center">
<%= form_for #contact do |f| %>
<div class="col-md-6 text-faded">
<%= f.label :name %>
<%= f.text_field :name, required: true, :class => "form-control", :placeholder => "Name"%>
</div>
<div class="col-md-6 text-faded">
<%= f.label :email %>
<%= f.email_field :name, required: true, :class => "form-control", :placeholder => "Email" %>
</div>
<div class="col-md-12 text-faded">
<%= f.label :message %>
<%= f.text_area :message, as: :text, :class => "form-control", :rows=>"9", :placeholder => "Your message here.."%>
</div>
<div class="hidden">
<%= f.label :nickname %><br>
<%= f.text_field :nickname, hint:"leave this field blank"%>
</div>
<div class="col-md-4 col-md-offset-4">
<%= f.submit "Send Message", :class=> "btn btn-primary btn-block btn-lg" %>
</div>
<%end%>
</div>
</div>
</div>
</section>
Model:
class Contact<MailForm::Base
attribute :name, :validate => true
attribute :email, :validate => /\A([\w\.%\+\-]+)#([\w\-]+\.)+([\w]{2,})\z/i
attribute :message, :validate => true
attribute :nickname,:captcha => true
def headers
{
:subject => "Contact Form",
:to => "kurtco_91#hotmail.com",
:to => "yomi.89gm#gmail.com",
:from => %("#{name}" <#email>)
}
end
end
Routes:
Rails.application.routes.draw do
resources :contacts, only: [:new,:create]
get 'gmm/home'
get 'gmm/about'
get 'gmm/services'
get 'gmm/contact'
get '/change_locale/:locale', to: 'settings#change_locale', as: :change_locale
I think it must be a problem with the post verb or my routing but I did rake: routes several times and no progress. Thanks a lot for your help. I really appreciate it
Answer to Email showing in name field is you are actually saving email into name field.
change email field from this:
<%= f.email_field :name, required: true, :class => "form-control", :placeholder => "Email" %>
to this:
<%= f.email_field :email, required: true, :class => "form-control", :placeholder => "Email" %>
Answer to URL issue is:
in your controller after according to my assessment you should save the contact if u need. if contact save successfully you should redirect to new_contact_path.
controller should look like this:
def create
#contact=Contact.new(params[:contact])
#contact.request=request
if #contact.deliver
flash.now[:error]=nil
else
flash.now[:error]='Cannot send message.'
redirect_to new_contact_path
end
end