What does .1 mean in `../users/1/profile.1`

2019-09-17 00:22发布

/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

3条回答
做个烂人
2楼-- · 2019-09-17 00:49

Usually the point following a dot at the end of a url is the format, for instance.

/users/12.html
/users/12.js
/users/12/profiles.xml

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.

  • What does the users and profiles controllers look like in your routes file?
  • What does the link_to or url_for or *_url or *_path which generated this link look like?

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 to users_profiles_path(@user, @profile)

Update:

I put part of your routes file into a new rails app and got these routes

edit_user_profile GET    /users/:user_id/profile/edit(.:format) profiles#edit
     user_profile GET    /users/:user_id/profile(.:format)      profiles#show
                  PATCH  /users/:user_id/profile(.:format)      profiles#update
                  PUT    /users/:user_id/profile(.:format)      profiles#update

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.

查看更多
Melony?
3楼-- · 2019-09-17 01:03

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).

查看更多
何必那么认真
4楼-- · 2019-09-17 01:13

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.

user_profile_path(current_user, @profile)

To

user_profile_path
查看更多
登录 后发表回答