Keep getting "Param is missing or the value is empty" - ruby-on-rails

I keep getting the error mentioned above, even though my form object matches my controller object (most people who had this problem had mixed their objects up in similar questions). What exactly am I doing wrong here?
My code is below:
<!-- The form is here -->
<%= form_for(#user), url: {action: "/users/signup"}, html: {class: "signup_form"} do |f| %>
<%= label_tag(:firstname, "Firstname: ") %>
<%= f.text_field :firstname %>
<%= label_tag(:lastname, "Lastname: ") %>
<%= f.text_field :lastname %>
<%= label_tag(:username, "Username: ") %>
<%= f.text_field :username %>
<%= label_tag(:email, "Email: ") %>
<%= f.text_field :email %>
<%= label_tag(:password, "Password") %>
<%= f.password_field :password %>
<%= f.submit "Create Account" %>
<% end %>
And here's the controller:
class UsersController < ApplicationController
def create
#user = User.new(user_params)
#user.save
redirect_to #user
end
private
def user_params
params.require(:user).permit(:firstname, :lastname, :username,
:email, :password)
end
end
Would really appreciate some help and sorry if I missed something silly here, thanks in advance.

users_controller.rb
class UsersController < ApplicationController
def new
#user = User.new
end
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
format.html { redirect_to #user, success: 'Thanks for signing up!' }
format.json { render :show, status: :created, location: #user }
else
format.html { render :new }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
end
users/_form.html.erb
<%= form_for(#user) do |f| %>
<div class="field">
<%= f.label :first_name, "First name" %><br>
<%= f.text_field :first_name %>
</div>
<div class="field">
<%= f.label :last_name, "Last name" %><br>
<%= f.text_field :last_name %>
</div>
<div class="field">
<%= f.label :email, "Email" %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password, "Password" %><br>
<%= f.password_field :password %>
</div>
<div class="actions">
<%= f.submit "Sign Up" %>
</div>
<% end %>

Why do you have url: {action: "/users/signup"} in the form? It is much simpler if you do the following:
routes.rb
Rails.application.routes.draw do
resources :user
end
views/users/_form.html.erb
<%= form_for(#user), html: {class: "signup_form"} do |f| %>
controllers/users_controller.rb (add the following)
class UsersController < ApplicationController
def new
#user = User.new
end
end
If you do it like this, form_for will automatically detect whether or not the #user object has been saved in the database, and will route the form to the create or update method respectively.
I general I don't reccommend altering the standard RESTful routes unless absolutley necessary. A user is not likely going to look at yoursite.com/users/new in the URL and be upset or confused.

Related

Rails 4: can't update current user

I'm trying to update some specific values for current_user but I have had no luck with it. The values do not save and the page doesn't get redirected anywhere whatsoever. Here's the code for user controller in update
def update
#user = current_user
respond_to do |format|
if #user.update_attributes(user_params)
format.html { redirect_to #user, notice: 'User was successfully updated.' }
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit, notice: 'Update unsuccessful' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
def user_params
params.require(:user).permit(:username, :password, :password_confirmation, :email, :weight, :height, :age, :activity_level, :goal, :calorie_goal, :fat_goal, :carb_goal, :protein_goal, :fiber_goal, :sugar_goal)
end
I tried to use params[:user] or params[:current_user] instead of user_params but with no luck.. here's html
<h2>Set Up Your Profile</h2>
<% #user = current_user %>
<%= form_for(#user) do |f| %>
current user is <%= current_user.username %>
<div class="field">
<%= f.label :weight %><br>
<%= f.text_field :weight %>
</div>
<div class="field">
<%= f.label :height %><br>
<%= f.text_field :height %>
</div>
<div class="field">
<%= f.label :age %><br>
<%= f.number_field :age %>
</div>
<div class="field">
<%= f.label :activity_level %><br>
<%= f.number_field :activity_level %>
</div>
<div class="field">
<%= f.label :goal %><br>
<%= f.number_field :goal %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
here I tried form_for(current_user) as well but didn't work, too... Any ideas what's wrong here?

How do I create a two-step form in rails?

I have a question for rails. I'm creating a form for user to register. What I want to do is that after the user press "Submit" button I want to redirect the user to another page which shows all the information from the form filled by the user just now (read-only).
This is my controller
class PermitsController < ApplicationController
before_action :set_permit, only: [:show, :destroy]
def index
#permits = Permit.all
end
def new
#permits = Permit.new
end
def create
#permits = current_user.permits.build(permit_params)
if #permits.save
redirect_to invoice_path
else
render 'new'
end
end
def destroy
Permit.destroy_all(user_id: current_user)
respond_to do |format|
format.html { redirect_to root_path, notice: 'Permit was successfully canceled.' }
format.json { head :no_content }
end
end
def invoice
#permits = current_user.permits(permit_params)
end
def show
#user = User.find(params[:id])
#permits = #user.permits.paginate(permit_params)
end
def update
#permits = Permit.where(user_id: current_user).take
respond_to do |format|
if #permits.update(permit_params)
format.html { redirect_to root_path}
flash[:success] = "Permit successfully updated"
format.json { render :show, status: :ok, location: #user }
else
format.html { render :edit }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_permit
#permits = Permit.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def permit_params
params.require(:permit).permit(:vehicle_type, :name, :studentid, :department, :carplate, :duration, :permitstart, :permitend)
end
end
This is the form filled by user
<% provide(:title, 'New Permit') %>
<h1>Permit Application</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#permits) do |f| %>
<%= f.label :"Vehicle" %>
<%= f.text_field :vehicle_type, class: 'form-control' %>
<%= f.label :"License Plate" %>
<%= f.text_field :carplate, class: 'form-control' %>
<%= f.label :"Student ID" %>
<%= f.text_field :studentid, class: 'form-control' %>
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :"Department of applicant" %>
<%= f.text_field :department, class: 'form-control' %>
<%= f.label :permit_start %>
<%= f.date_select :permitstart, class: 'form-control' %>
<%= f.label :permit_end %>
<%= f.date_select :permitend, class: 'form-control' %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
You could add an additional action between new and create.
# config/routes.rb
resources :permit do
collection do
post :confirm
end
end
The reason that we use POST even if the route does not create a resource is that we don't want to pass any user info in the request URL.
class PermitsController < ApplicationController
# POST /permits/confirm
def confirm
#fields = %i[vehicle_type, carplate, studentid, name, department, permitstart, permitend]
#permit = current_user.permits.build(permit_params)
render :new and return unless #permit.valid?
end
end
render :new and return unless #permit.valid? shortcuts the process and renders the :new form again if the input is not valid in the first place.
Since we are using POST we need a form for both the new.html.erb and confirm.html.erb all duplicating all those inputs would not be great so lets extract them to a partial:
<% # /views/permits/_inputs.html.erb %>
<%
input_options ||= {}
input_options[:class] ||= 'form-control'
%>
<%= f.label :"Vehicle" %>
<%= f.text_field :vehicle_type, input_options%>
<%= f.label :"License Plate" %>
<%= f.text_field :carplate, input_options %>
<%= f.label :"Student ID" %>
<%= f.text_field :studentid, input_options %>
<%= f.label :name %>
<%= f.text_field :name, input_options %>
<%= f.label :"Department of applicant" %>
<%= f.text_field :department, input_options %>
<%= f.label :permit_start %>
<%= f.date_select :permitstart, input_options %>
<%= f.label :permit_end %>
<%= f.date_select :permitend, input_options %>
So lets point the new.html.erb form so that it submits to /permits/confirm:
<% provide(:title, 'New Permit') %>
<h1>Permit Application</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#permits, url: '/permits/confirm_permits_path') do |f| %>
<% render partial: :inputs %>
<%= f.submit "Submit", class: "btn btn-primary" %>
<% end %>
</div>
</div>
And create a /views/permits/confirm.html.erb view:
<% provide(:title, 'Confirm Permit application') %>
<h1>Confirm Permit application</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#permits) do |f| %>
<% render partial: :inputs, input_options: { readonly: 'readonly' } %>
<% end %>
</div>
</div>

Ruby on Rails: Populate dropdown with two fields of database record

In my database I have a Users table that looks something like:
User_ID Firstname Surname Company
1 Steve Jobs Apple
2 Bill Gates Microsoft
What I am trying to do is make a drop down menu in a form that would allow a user to choose from selecting their name or their company, e.g. when Steve Jobs is logged in he can either select "Steve" or "Apple" in the drop down menu.
What I have tried so far is the following:
<%= f.select :from_name, [session[:user_id],session[:user_id]] %>
Which obviously didn't work because it only returns the user id of the logged in user.
<%= f.select :from_name, [#user.firstname,#user.company] %>
Which gave me the error undefined methodfirstname for nil:NilClass`
My Users controller is as follows:
class UsersController < ApplicationController
before_filter :check_authorization, :except => [:show, :new, :create, :search ]
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
def edit
#user = User.find(params[:id])
end
def create
#user = User.new(user_params)
#user.role = "customer"
if #user.save
session[:user_id] = #user.id
# Save a copy of the email address entered by the user into the Accounts table
#account = Account.create(email: params[:user][:primaryemailaddress], user_id: session[:user_id])
redirect_to root_path
else
render 'new'
end
end
def update
#user = User.find(params[:id])
if #user.update(user_params)
redirect_to #user
else
render 'edit'
end
end
def destroy
#user = User.find(params[:id])
#user.destroy
redirect_to users_path
end
private
def user_params
params.require(:user).permit(:title, :firstname, :surname, :housenumber, :street, :city, :postcode, :company, :primaryemailaddress, :password)
end
end
And my _form.html.erb is:
<%= form_for(#email) do |f| %>
<% if #email.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#email.errors.count, "error") %> prohibited this email from being saved:</h2>
<ul>
<% #email.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<p>
<%= f.label :from_name %><br>
<%= f.select :from_name, [current_user.firstname, current_user.company] %>
</p>
<p>
<%= f.label :From_Email_Address %><br>
<%= f.collection_select :account_id, Account.where(user_id: session[:user_id]),
:id,:email %>
</p>
<p>
<%= f.label :to %><br>
<%= f.text_field :to %>
</p>
<p>
<%= f.label :cc %><br>
<%= f.text_field :cc %>
</p>
<p>
<%= f.label :bcc %><br>
<%= f.text_field :bcc %>
</p>
<p>
<%= f.label :subject %><br>
<%= f.text_field :subject %>
</p>
<p>
<%= f.label :message %><br>
<%= f.text_field :message %>
</p>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
I'm not too sure how to solve this issue, can someone please help.
#BenSmith I guess you are accessing EmailsController. And on that controller's new or edit method there is no #user variable.
In your edit and new method add
#user = User.find(session[:user_id])
undefined method firstname for nil:NilClass
Seems like some how #user is nil
create a helper and check for presence of #user
<%= f.select :from_name, dropdown_values %>
application_helper.rb
def dropdown_values
if #user.present?
[#user.firstname, #user.company]
else
['default', 'values']
end
end
<p>
<%= f.label :from_name %><br>
<%= f.select :from_name, [current_user.firstname, current_user.company] if #user.present?%>
</p>
because User.new time create blank object doesn't find username.i hope its will be help you.

Rails - Register a user in stages. Starting with username

I want to change my user registration. Instead of letting the users fill in all the details at once I would like the user to fill in only the username and bring him to the registration page with the username filled in and he has to add the rest of the details.
What I have now at my landingpage (basically copy of the new user page):
<%= form_for(#user) do |f| %>
<%= render 'shared/error_messages' %>
<%= f.label :name, "Username" %>
<%= 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-success btn-md createbutton"%>
<% end %>
My registration page is at registation_path
<% provide(:title, 'Register') %>
<div class = "container center">
<body class ="formbody">
<center><h1>Sign up</h1></center>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#user) do |f| %>
<%= 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-success createbutton"%>
</div>
</div>
</div>
<% end %>
</body>
I would like the user to fill in the name in 1 form at the landing page and get redirected to the registration form with the name filled in.
edit: added the controller
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update]
before_action :correct_user, only: [:edit, :update]
def new
#user = User.new
end
def index
#users = User.all
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(user_params)
flash.now[:success] = "Profile updated"
redirect_to #user
else
render 'edit'
end
end
def create
#user = User.new(user_params) # Not the final implementation!
if #user.save
log_in #user
flash.now[:success] = "Account Created Succesfully"
redirect_to #user
else
render 'new'
end
end
def show
#user = User.find(params[:id])
end
def logged_in_user
unless logged_in?
store_location
flash[:danger] = "Please log in."
redirect_to login_url
end
end
# Confirms the correct user.
def correct_user
#user = User.find(params[:id])
redirect_to(root_url) unless current_user?(#user)
end
private
def user_params
params.require(:user).permit(:name, :email, :password,
:password_confirmation)
end
end

form updating nested attributes when not required

I have a Users model that can have many Groups through Memberships. If a user is a member of a group, and you submit the form with no changes, it will attempt to update the membership table and put group_id to 0 as per below.
My model for User accepts_nested_attributes_for Memberships
In my User controller...
def edit
#user = User.find(params[:id])
#groups = Group.current
#membership = #user.memberships.build
end
def update
#user = User.find(params[:id])
#groups = Group.current
if params[:memberships][:group_id] != ""
#membership = #user.memberships.build(:group_id => params[:memberships][:group_id])
end
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to admin_users_url, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
#if params[:memberships][:group_id] == ""
# #membership = #user.memberships.build
#end
format.html { render action: "edit" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
In my user form...
<%= form_for([:admin,#user]) do |f| %>
---
<div class="field">
<%= f.label :email %><br />
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password %><br />
<%= f.password_field :password %>
</div>
<div class="field">
<%= f.label :password_confirmation %><br />
<%= f.password_field :password_confirmation %>
</div>
<%= f.fields_for :memberships do |builder| %>
<div class="field">
<% if builder.object.new_record? %>
<%= builder.label :group_id %><br />
<%= collection_select(:memberships, :group_id, #groups, 'id', 'name', {:include_blank => true}) %>
<% else %>
<%= builder.label :group_id %><br />
<%= builder.text_field :group_id, :value => Group.find(Membership.find(builder.object).group_id).name, :readonly => true %> <%= link_to 'Remove', [:admin,#user,Membership.find(builder.object)], :confirm => 'Are you sure?', :method => :delete %>
<% end %>
</div>
<% end %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
The form is submitting the data
Parameters: {"utf8"=>"✓",
"authenticity_token"=>"6Vp9sgMySzRm2CU9Dko+Jpf6yaBkXjKkt10UDbb8dcw=",
"user"=>{"email"=>"asdfasdf#asdf.com",
"password"=>"[FILTERED]", "password_confirmation"=>"[FILTERED]",
"memberships_attributes"=>{"0"=>{"group_id"=>"Cricket Maidstone June 2012",
"id"=>"18"}}},
"memberships"=>{"group_id"=>""},
"commit"=>"Update User", "id"=>"25"}
All I want to do is for the form to check and if there is nothing in the collection_select field to not update the memberships table, but still update any changes to email/password. Can anyone see a way to do this?
In your model, declare a parallel field with attr_accessor:
attr_accessor :memberships_attributes_input
def memberships_attributes_input
memberships
end
def memberships_attributes_input=value
# Update memeberships if required evaluating 'value'.
end
Use this new field in your form instead "memberships".

Resources