Split Form User Update Rails - ruby-on-rails

Recently, I decided to split my User Form into an Edit & Account Form.
User Edit Form
-Name
-Username
-AboutMe
User Account Form
-Email
-Password
-Password Confirmation
The routes work fine and everything gets updated accordingly. But for some reason, when my User Model validates the Email Presence & it Fails, it renders the Edit Form with the appropriate Error Messages as oppose to the Account Form.
How can I set up my Update Method in my Controller to know which form to Render with the appropriate error messages?
Model
class User < ActiveRecord::Base
attr_accessible :name, :email, :password, :password_confirmation, :username
validates :username, :presence => true,
:length => { :maximum => 15 },
:format => { :with => VALID_UNAME_REGEX },
:uniqueness => { :case_sensitive => false }
validates :email, presence: true,
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
validates :password, presence: true, length: { minimum: 6 }, :if => :password #only validate if password changed!
validates :password_confirmation, presence: true, :if => :password
end
Views
Edit View
<%= form_for #user, :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="statictitle">Your Profile</div>
<%= f.text_field :username, placeholder: "Username..", :class => "form-control" %>
<%= f.text_field :name, placeholder: "Name", :class => "form-control" %>
<%= f.text_area :bio, placeholder: "About yourself in 160 characters or less...", class: "textinput" %>
<%= f.submit "Update Profile", class: "btn btn-primary" %><br>
<% end %>
Account View
<%= form_for #user, :html => { :multipart => true } do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<div class="statictitle">Your Account</div>
<%= f.text_field :email, placeholder: "Email", :class => "form-control" %>
<%= f.password_field :password, placeholder: "Password", :class => "form-control" %>
<%= f.password_field :password_confirmation, placeholder: "Password Confirmation", :class => "form-control" %>
<%= f.submit "Update Account", class: "btn btn-primary" %><br>
<% end %>
Controller
class UsersController < ApplicationController
def edit
#user = User.find_by_username(params[:id])
end
def account
#title = "Account"
#user = User.find_by_username(params[:id])
end
def update
#user = User.find(current_user.id)
if #user.update_attributes(params[:user])
flash[:success] = "Profile updated"
sign_in #user
redirect_to user_url
else
render 'edit' ###I can't seem to figure out how to render the correct form
end
end
end
Routes
resources :users do
member do
get :account
end
end

You can check the HTTP Referer in this case which will tell you where the request came from and accordingly render your view.
for eg:
if URI(request.referer).path == edit_user_path
render :edit
else
render :account
end

Related

Chapter 7 Errors, Ruby on Rails tutorial

No matter what I write there I will always get these errors, I have read chapter twice, I don't understand what I am doing wrong.
Here's my code at GitHub
Here's a screenshot of errors.
user_controller.rb
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def create
#user = User.new(params[user_params])
if #user.save
redirect_to user_url(#user)
#Handle a successfull save
else
render 'new'
end
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
end
Model
class User < ActiveRecord::Base
before_save { self.email = email.downcase }
validates :name, presence: true, length: { maximum: 50 }
VALID_EMAIL_REGEX = /\A[\w+\-.]+#[a-z\d\-.]+\.[a-z]+\z/i
validates :email, presence: true, length: { maximum: 255 },
format: { with: VALID_EMAIL_REGEX },
uniqueness: { case_sensitive: false }
has_secure_password
validates :password, presence: true, length: { minimum: 6 }
end
Form
<% provide(:title, 'Sign up') %>
<h1>Sign up</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#user) do |f| %>a
<%= render '/shared/error_messages' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :email %>
<%= f.email_field :email, class: 'form-control' %>
<%= f.label :password %>
<%= f.password_field :password, class: 'form-control' %>
<%= f.label :password_confirmation, "Confirmation" %>
<%= f.password_field :password_confirmation, class: 'form-control' %>
<%= f.submit "Create my account", class: "btn btn-primary" %>
<% end %>
</div>
</div>
Change line
#user = User.new(params[user_params])
to
#user = User.new(user_params)
in UsersController.
Everything else looks fine.

Setting Default Value in .build method

Im trying to submit a nested form when you create a school, you can also create a admin with it. When I try to save the form with the default value of owner set to true and status set to active, it saves the form but doesnt save those values in the database
class SchoolsController < ApplicationController
before_filter :authenticate_admin!, except: [:index, :new, :create]
def show
#school = School.friendly.find(params[:id])
end
def new
#school = School.new
#admin = #school.admins.build(:owner => true, :status => "active")
end
def create
#school = School.new(school_params)
if #school.save
redirect_to new_admin_session_path
else
render 'new'
end
end
def edit
#school = School.find_by_slug(params[:id])
end
def update
#school = School.find_by_slug(params[:id])
if #school.update_attributes(school_params)
redirect_to :action => 'show', :id => #school
else
render :action => 'edit'
end
end
def team
#teams = Admin.all
end
private
def school_params
params.require(:school).permit(:school_name, :latitude, :longitude, :radius, admins_attributes: [ :first_name, :last_name, :email, :password, :password_confirmation, :image ])
end
end
class School < ActiveRecord::Base
has_many :admins
accepts_nested_attributes_for :admins
extend FriendlyId
friendly_id :school_name, use: :slugged
def should_generate_new_friendly_id?
school_name?
end
# Validation
validates :school_name, presence: true, uniqueness: true
validates :latitude, presence: true
validates :longitude, presence: true
validates :radius, presence: true, numericality: { only_integer: true }
end
%nav.navbar.navbar-default.navbar-fixed-top{role:"navigation"}
%div.container
%div.navbar-header
%button.navbar-toggle.collapsed{"data-toggle" => "collapse", "data-target" => "#navbar", "aria-expanded" => "false", "aria-controls" => "navbar"}
%span.sr-only Toggle Navigation
%span.icon-bar
%span.icon-bar
%span.icon-bar
%a.navbar-brand{"href" => "/", "id"=> "brand"} QuickAlert
%div#navbar.collapse.navbar-collapse
%ul.nav.navbar-nav.main-menu
%li.active
%a{"href" => "#"} Home
%li
%a{"href" => "#about"} About
%li
%a{"href" => "#contact"} Contact
%div.container-fluid
%div.row
%div.school-create
- if #school.errors.any?
%ul
- #school.errors.full_messages.each do |msg|
%li
= msg
%div#map-check
%h2.header School Info
= form_for #school do |f|
= f.label :school_name, "School Name"
= f.text_field :school_name, :class => 'form-control'
= f.label :latitude, "Latitude"
= f.text_field :latitude, :class => 'form-control', :id => "latitude"
= f.label :longitude, "Longitude"
= f.text_field :longitude, :class => 'form-control', :id => "longitude"
= f.label :radius, "Radius"
= f.text_field :radius, :class => 'form-control', :id => "radius"
%div.admin-fields
%h2.header Admin Info
= f.fields_for :admins do |ff|
= ff.label :first_name
= ff.text_field :first_name, :class => 'form-control'
= ff.label :last_name
= ff.text_field :last_name, :class => 'form-control'
= ff.label :email
= ff.text_field :email, :class => 'form-control'
= ff.label :password
= ff.password_field :password, :class => 'form-control'
= ff.label :password_confirmation
= ff.password_field :password_confirmation, :class => 'form-control'
= ff.file_field :image
= f.submit :class => 'submit-button btn btn-primary'

Editing attribute saved with .build

Im trying to edit a field so that it goes in the database as the owner boolean being set to true when the user creates the account. I get the error undefined method `owner
= form_for #school do |f|
= f.label :school_name, "School Name"
= f.text_field :school_name, :class => 'form-control'
= f.label :latitude, "Latitude"
= f.text_field :latitude, :class => 'form-control'
= f.label :longitude, "Longitude"
= f.text_field :longitude, :class => 'form-control'
= f.label :radius, "Radius"
= f.text_field :radius, :class => 'form-control'
= f.fields_for :admins do |ff|
= ff.label :email
= ff.text_field :email, :class => 'form-control'
= ff.label :password
= ff.password_field :password, :class => 'form-control'
= ff.label :password_confirmation
= ff.password_field :password_confirmation, :class => 'form-control'
= f.submit :class => 'submit-button'
def new
#school = School.new
#school.admins.build
#school.admins.owner = true
end
def create
#school = School.new(school_params)
if #school.save
redirect_to :action => 'show', :id => #school
else
render 'new'
end
Because #school.admins is a collection of multiple admins, so it doesn't have the owner method, that exists on the individual admin objects within that collection.
When you call #school.admins.build it returns a new instance of Admin, but you're not doing anything with that instance. You need to put it in a variable, and then assign a value to its owner attribute. That will look like this:
#school = School.new
#admin = #school.admins.build
#admin.owner = true
But the build method takes an attributes argument, so you can shorten that to this:
#school = School.new
#admin = #school.admins.build(owner: true)
Don't forget that you'll also need to save this object at some point.

Devise redirects to index action on error

I am using devise, and is having an issue if you try to signup with an existing email.
When you signup you do it from this url:
http://localhost:3000/accounts/new
So I have an account, where I add a user (devise). If I try to signup as a user which already exists I get the correct error:
"Users email has already been taken"
But it redirects to http://localhost:3000/accounts
The controller looks a bit like this:
def create
name = account_params[:name]
first_name = Modules::NameHelpers.get_first_name(name)
last_name = Modules::NameHelpers.get_last_name(name)
#account = Account.new(account_params_wo_user_name)
#account.users.first.first_name = first_name
#account.users.first.last_name = last_name
respond_to do |format|
if #account.save
sign_in #account.users.first
format.html { redirect_to root_path, notice: "Thanks for signing up." }
format.json { render action: 'show', status: :created, location: #account }
else
format.html { render action: 'new' }
format.json { render json: #account.errors, status: :unprocessable_entity }
end
end
end
I can't seem to find what redirects to the index page.
Update:
Here is the form:
<%= form_for(#account) do |f| %>
<%= render 'shared/error_messages', :object => f.object %>
<div>
<%= f.label :name, 'Account Name' %> <br />
<%= f.text_field :name, :required => true, :placeholder => 'Your account name' %>
</div>
<%= f.fields_for :users do |user_form| %>
<div><%= user_form.label :name %><br />
<%= user_form.text_field :name, :autofocus => true, :required => true, :placeholder => 'Your name' %></div>
<div><%= user_form.label :email %><br />
<%= user_form.email_field :email, :required => true, :placeholder => 'Your email' %></div>
<div><%= user_form.label :password, :required => true %><br />
<%= user_form.password_field :password, :required => true, :placeholder => 'Enter a 8 character password'%></div>
<div><%= user_form.label :password_confirmation, :required => true %><br />
<%= user_form.password_field :password_confirmation, :required => true, :placeholder => 'Confirm password' %></div>
<% end %>
<div><%= f.submit "Sign up" %></div>
<% end %>

param is missing or the value is empty

I am new to Rails. Getting the error below. I understand what the issue is, but not sure how to fix it?
Error - param is missing or the value is empty: customer
def customer_params
params.require(:customer).permit(
:first_name,
:last_name,
:email,
:password,
:password_confirmation)
end
end
DetailsController.rb
class My::Account::DetailsController < MyController
def show
#customer = current_user
end
def update
#customer = current_user
#customer.update_attributes(customer_params)
if #customer.errors.any?
render :action => :show
else
redirect_to my_account_details_path, :notice => 'Account details updated'
end
end
private
def customer_params
params.require(:customer).permit(
:first_name,
:last_name,
:email,
:password,
:password_confirmation)
end
end
View
.account.container
.row
= render :partial => '/my/account/sidebar'
.section
%h2 Your account details
= simple_form_for #customer, :url => my_account_details_path, :method => :put, :html => { :class => 'form-horizontal'} do |form|
.field
= form.input :first_name
.field
= form.input :last_name
.field
= form.input :email, :as => :email
%hr
%h4 Leave password fields blank to keep the existing password
%hr
.field
= form.input :password, :input_html => { :value => '' }
.field
= form.input :password_confirmation, :input_html => { :value => '' }
.field-actions
%button.btn.btn-primary{type: "submit"} Save
It is because it is coming through as user and not customer. Which I believe is because you are using current_user which is a User and not a Customer (guessing from the code). Change it to be params.require(:user).permit(blah)

Resources