/What does the .1
mean in ../users/1/profile.1
? In editing an associated model in a one to one relationship, such as a user has one profile; it updates and redirected to ..users/user_id/profile.#
instead of ../users/user_d/profile
.
In the form_for, i used form_for [:user, @profile]
to cover for the namespace through nested resources, but i don't understand why the .#
. In an attempt to see if the link will cause my program to break, i clicked home (to take me back to my root page, basically reloading the profile as i had programmed for a logged in user), it reverts back to ../users/user_d/profile
.
Using a debugging gem i get:
--- !ruby/hash:ActionController::Parameters
action: show
controller: profiles
user_id: '1'
format: '1'
What is format: '1'
? Any explanation appreciated.
Adding my Code
USER.RB
class User < ActiveRecord::Base
attr_accessor :remember_token
before_save {self.email = email.downcase }
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-]+(\.[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 }, allow_nil: true
has_one :profile, dependent: :destroy
accepts_nested_attributes_for :profile
end
PROFILE.RB
class Profile < ActiveRecord::Base
validates :name, presence: true, length: { maximum: 50 }
validates :street, :city, :state, :zipcode, presence: true
belongs_to :user
end
Their controllers
USER CONTROLLER
class UsersController < ApplicationController
before_action :logged_in_user, only: [:index, :edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
before_action :admin_user, only: :destroy
def new
@user = User.new
@profile = @user.build_profile
end
def create
@user = User.new(user_params)
if @user.save
log_in @user
flash[:success] = "Welcome to the Mini Olympics"
redirect_to user_profile_path(current_user, @profile)
else
render 'new'
end
end
def show
@user = User.find(params[:id])
end
def edit
# Commented out the code, as its redundant due to the line 'before_action :correct_user'
# @user = User.find(params[:id])
end
def update
# Commented out first line of the code, as its redundant due to the line 'before_action :correct_user'
# @user = User.find(params[:id])
if @user.update_attributes(user_params)
flash[:success] = "profile updated"
#redirect_to @user
redirect_to user_profile_path(current_user, @profile)
else
render 'edit'
end
end
def index
@users = User.paginate(page: params[:page], per_page: 15)
end
def destroy
User.find(params[:id]).destroy
flash[:success] = "User deleted"
redirect_to users_url
end
private
def user_params
params.require(:user).permit(:id, :email, :password, :password_confirmation, profile_attributes: [:name,
:street, :city, :state, :zipcode] )
end
# Before filters
# Confirms a logged-in user.
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) # '@user == current_user' = 'current_user?(@user)'
end
# Confirms an admin user.
def admin_user
redirect_to(root_url) unless current_user.admin?
end
end
PROFILE CONTROLLER
class ProfilesController < ApplicationController
def edit
@profile = User.find(params[:user_id]).profile
end
def show
@profile = User.find(params[:user_id]).profile
end
def update
@profile = User.find(params[:user_id]).profile
if @profile.update_attributes(profile_params)
flash[:success] = "profile updated"
redirect_to user_profile_path(current_user, @profile)
else
render 'edit'
end
end
private
def profile_params
params.require(:profile).permit(:id, :name, :street, :city, :state, :zipcode)
end
end
Profile edit form
<% provide(:title, "Edit Profile") %>
<h1>Update your profile</h1>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for [:user, @profile] do |f| %>
<%= render 'fields', f: f %>
<%= f.submit "Save changes", class: "btn btn-primary" %>
<% end %>
</div>
</div>
APP/VIEWS/PROFILES/_FIELDS.HTML.ERB
<%= f.label :name %>
<%= f.text_field :name, class: 'form-control' %>
<%= f.label :street %>
<%= f.text_field :street, class: 'form-control' %>
<%= f.label :city %>
<%= f.text_field :city, class: 'form-control' %>
<%= f.label :state %>
<%= f.text_field :state, class: 'form-control' %>
<%= f.label :zipcode %>
<%= f.text_field :zipcode, class: 'form-control' %>
ROUTES FOLDER
Rails.application.routes.draw do
root 'static_pages#home'
get 'help' => 'static_pages#help'
get 'about' => 'static_pages#about'
get 'contact' => 'static_pages#contact'
get 'signup' => 'users#new'
get 'login' => 'sessions#new'
post 'login' => 'sessions#create'
delete 'logout' => 'sessions#destroy'
resources :users do
resource :profile, only: [:show, :edit, :update ]
end
end
Usually the point following a dot at the end of a url is the format, for instance.
It looks like you've got a mal-formed url being generated somewhere which is passing the ID in as the format, as well as the id parameter.
That's the explanation, I'm not sure how to get rid of it without a little more information.
Although my best guess is that you could just do
form_for(@profile)
to tidy this up. Then redirect in your create or update method tousers_profiles_path(@user, @profile)
Update:
I put part of your routes file into a new rails app and got these routes
I missed the fact that you used resource instead of resources, so that each user has only one profile.
In the redirect, use
user_profile_path(@user)
, you don't need to pass in the profile, the path only has one id in it, and that's the user_id.the "dot something" at the end of a route indicates the format you want to get. So if you type profile.json, rails will know you want json answer and will render accordingly in the controller (if this one is supported).
Other have answered about the format.
I am currently using Rails 5.1.5 and experienced similar situation. However, once I removed the instance variables that I was passing, the ids did not append to the url and you can still access them in the views.
To