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?
Related
I'm almost certain I know what the problem is, and if I'm correct, I just can't find where the problem is lying.
When triple-nesting with the cocoon gem, I'm having what seems to be an error with incorrect pluralisation. I have 3 resources, Developments > Lots > Listings, where Developments is the grandparent, Lots is the parent and Listings is the child.
The error I'm getting is unknown attribute 'development_id' for Lot. stemming from ActiveModel::UnknownAttributeError in Developments#new. I've checked my models and partials and have been playing around with them. Here is my code:
developments_controller.rb
class DevelopmentsController < ApplicationController
before_action :set_development, only: %i[ show edit update destroy ]
# GET /developments or /developments.json
def index
#developments = Development.all
end
# GET /developments/1 or /developments/1.json
def show
end
# GET /developments/new
def new
#development = Development.new
end
# GET /developments/1/edit
def edit
end
# POST /developments or /developments.json
def create
#development = Development.new(development_params)
respond_to do |format|
if #development.save
format.html { redirect_to #development, notice: "Development was successfully created." }
format.json { render :show, status: :created, location: #development }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #development.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /developments/1 or /developments/1.json
def update
respond_to do |format|
if #development.update(development_params)
format.html { redirect_to #development, notice: "Development was successfully updated." }
format.json { render :show, status: :ok, location: #development }
else
format.html { render :edit, status: :unprocessable_entity }
format.json { render json: #development.errors, status: :unprocessable_entity }
end
end
end
# DELETE /developments/1 or /developments/1.json
def destroy
#development.destroy
respond_to do |format|
format.html { redirect_to developments_url, notice: "Development was successfully destroyed." }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_development
#development = Development.find(params[:id])
end
# Only allow a list of trusted parameters through.
def development_params
params.require(:development).permit(:development_name, :development_type, :development_address, :description, :estimated_completion_date, :body_corp,
lots_attributes: [:id, :status, :stage, :land_size, :price, :eta, :_destroy,
listings_attributes: [:id, :lot_number, :price, :type, :bed, :bath, :car, :house_size, :rent, :_destroy]])
end
end
development.rb (model)
class Development < ApplicationRecord
has_many :lots
accepts_nested_attributes_for :lots, reject_if: :all_blank, allow_destroy: :true
end
Lot.rb (model)
class Lot < ApplicationRecord
has_many :listings
accepts_nested_attributes_for :listings, reject_if: :all_blank, allow_destroy: :true
belongs_to :development
end
Listing.rb (model)
class Listing < ApplicationRecord
belongs_to :lot
end
_form.html.erb (partial)
<%= form_for #development do |f| %>
<div class="field">
<%= f.label :development_name%>
<%= f.text_field :development_name%>
</div>
<div class="field">
<%= f.label :development_type %>
<%= f.text_field :development_type %>
</div>
<div class="field">
<%= f.label :development_address %>
<%= f.text_field :development_address %>
</div>
<div class="field">
<%= f.label :description %>
<%= f.text_area :description %>
</div>
<div class="field">
<%= f.label :estimated_completion_date %>
<%= f.date_select :estimated_completion_date %>
</div>
<div class="field">
<%= f.label :body_corp %>
<%= f.number_field :body_corp %>
</div>
<div id="listings">
<%= f.fields_for :lots do |lot| %>
<%= render 'lot_fields', f: lot %>
<% end %>
<div class="links">
<%= link_to_add_association 'add lot', f, :lots %>
</div>
</div>
<%= f.submit %>
<% end %>
_lot_fields.html.erb (partial)
<div class="nested-fields">
<h3> New Lots </h3>
<div class="field">
<%= f.label :status %>
<br/>
<%= f.text_field :status %>
</div>
<div class="field">
<%= f.label :stage %>
<br/>
<%= f.text_field :stage %>
</div>
<div class="field">
<%= f.label :land_size %>
<br/>
<%= f.text_field :land_size %>
</div>
<div class="field">
<%= f.label :price %>
<br/>
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :eta %>
<br/>
<%= f.text_field :eta %>
</div>
<%= link_to_remove_association "remove lot", f %>
</div>
_listing_fields.html.erb (partial)
<div class="nested-fields">
<h3> New Listing </h3>
<div class="field">
<%= f.label :status %>
<br/>
<%= f.text_field :status %>
</div>
<div class="field">
<%= f.label :stage %>
<br/>
<%= f.text_field :stage %>
</div>
<div class="field">
<%= f.label :land_size %>
<br/>
<%= f.text_field :land_size %>
</div>
<div class="field">
<%= f.label :price %>
<br/>
<%= f.text_field :price %>
</div>
<div class="field">
<%= f.label :eta %>
<br/>
<%= f.text_field :eta %>
</div>
<%= link_to_remove_association "remove listing", f %>
</div>
new.html.erb
<h1>New Development</h1>
<%= render 'form', development: #development %>
<%= link_to 'Back', developments_path %>
I have a clone project of this and I noticed in the schema.rb that there is a key difference:
t.index ["developments_id"], name: "index_lots_on_developments_id"
I believe it should be development_id instead of being pluralised, but I'm not sure where/how this needs to be changed. I'm under the impression you should never alter a schema file.
Any help is greatly appreciated!
Exactly, it should be :
t.index ["development_id"], name: "index_lots_on_development_id"
You have to rewrite a migration with
def change
remove_index :lots, name: "index_lots_on_developments_id"
add_reference :lots, :development, index: true
end
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.
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>
I have a User model, which has_one prestataire and has_one employeur. Previously on stackoverflow, someone advised me to declare singular resources, like:
resources :users do
resource: employeur
resource: prestataire
end
Instead of:
resources :users do
resources: employeurs
resources: prestataires
end
Thanks to rails, I didn't had to singularize all my controllers and views name files. Yet, when I create a user and am redirected to the employeur form, I get undefined method `user_employeurs_path', which is right since I only have a user_employeur_path. But I didn't ask for the plural in my user controller. Rails indicates that this NoMethodError happens in the first line of my employeur form <%= form_for [#user, #employeur] do |f| %>, where one is redirected when a user is saved.
class UsersController < ApplicationController
#TODO index user doit être suprimé quand inutile pour dev
def index
#users = User.all
end
def show
#user = User.find(params[:id])
end
def new
#user = User.new
end
# GET /users/1/edit
def edit
#user = User.find(params[:id])
end
# POST /users
# POST /users.json
def create
#user = User.new(user_params)
respond_to do |format|
if #user.save
if params[:commit] == 'Prestataire'
format.html { redirect_to new_user_prestataire_path(user_id: #user), notice: "Renseignez vos informations d'employeur" }
format.json { render action: 'show', status: :created, location: #user }
else
format.html { redirect_to new_user_employeur_path(user_id: #user), notice: "Renseignez vos informations de prestataire" }
format.json { render action: 'show', status: :created, location: #user }
end
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /users/1
# PATCH/PUT /users/1.json
def update
#user = User.find(params[:id])
respond_to do |format|
if #user.update(user_params)
if params[:commit] == 'Prestataire'
format.html { redirect_to new_user_prestataire_path(user_id: #user), notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { redirect_to new_user_employeur_path(user_id: #user), notice: "User was successfully updated." }
format.json { head :no_content }
end
else
format.html { render action: 'edit' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.json
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to users_url }
format.json { head :no_content }
end
end
private
def user_params
params.require(:user).permit(:email, :password, :password_confirmation, :surname, :forename, :civility, :phone)
end
end
User form:
<%= form_for(#user) do |f| %>
<% if #user.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#user.errors.count, "error") %> prohibited this user from being saved:</h2>
<ul>
<% #user.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :civility, 'Titre de civilité: ' %><br>
<%= f.text_field :civility %>
</div>
<div class="field">
<%= f.label :forename, 'Prénom: ' %><br>
<%= f.text_field :forename %>
</div>
<div class="field">
<%= f.label :surname, 'Nom de famille: ' %><br>
<%= f.text_field :surname %>
</div>
<div class="field">
<%= f.label :email, 'Email: ' %><br>
<%= f.text_field :email %>
</div>
<div class="field">
<%= f.label :password, 'Mot de passe: ' %><br>
<%= f.password_field :password, size: 40 %>
</div>
<div class="field">
<%= f.label :password_confirmation, 'Confirmation de mot de passe: ' %><br>
<%= f.password_field :password_confirmation, size: 40 %>
</div>
<div class="field">
<%= f.label :phone, 'Numéro de téléphone: ' %><br>
<%= f.text_field :phone %>
</div>
<div class="actions">
<%= f.submit "Employeur" %>
<%= f.submit "Prestataire" %>
</div>
<% end %>
Employeur form:
<%= form_for [#user, #employeur] do |f| %>
<% if #employeur.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#employeur.errors.count, "error") %> prohibited this employeur from being saved:</h2>
<ul>
<% #employeur.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :siren, 'Siren: ' %><br>
<%= f.text_field :siren %>
</div>
<div class="field">
<%= f.label :societe, 'Société: ' %><br>
<%= f.text_field :societe %>
</div>
<div class="field">
<%= f.label :code_postal, 'Code Postal: ' %><br>
<%= f.text_field :code_postal %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
As for my new.html document for employeur:
<h1>New employeur</h1>
<%= render 'form' %>
Here is what's happening:
when you pass <%= form_for [#user, #employeur] do |f| %>, Rails will connect the objects (#user & #employeur) in the order you passed and the then append path to it. So this becomes user_employeurs_path. by convention it will pluralize your the last object (employeur) to infer your controller's name. that's how it gets: user_employeurs_path
so you would either have to pluralize your controller's resources to follow the convention. Or pass url to your path:
<%= form_for [#user, #employeur], url: user_employeur_path do |f| %>
I believe you can use url parameter in this case. Try something like:
<%= form_for [#user, #employeur], url: user_employeur_path do |f| %>
...
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".