In my Rails App there is Device Model - User, and a Registry model( Each user has one registry).
I wanted to change my routes so that instead of:
"http://localhost:3000/registries/3"
it shows:
"http://localhost:3000/erinwalker"
So I changed routes to
match '/:name' => "registries#show"
And the show action in my controller to:
def show
@user = current_user
@user = User.find_by_name!(params[:name])
@registry = @user.registry
And it works, but when I create or update the registry now first it says:
Couldn't find User with name =
app/controllers/registries_controller.rb:21:in `show'
Even though the show action works?
The registries controller: class RegistriesController < ApplicationController before_filter :authenticate_user!, :except => :show load_and_authorize_resource
# GET /registries
# GET /registries.json
def index
@registries = Registry.all
@user = current_user
respond_to do |format|
format.html # index.html.erb
format.json { render json: @registries }
end
end
# GET /registries/1
# GET /registries/1.json
def show
@user = current_user
@user = User.find_by_name!(params[:name])
@registry = @user.registry
respond_to do |format|
format.html # show.html.erb
format.json { render json: @registry }
end
end
# GET /registries/new
# GET /registries/new.json
def new
@registry = Registry.new
@user = current_user
respond_to do |format|
format.html # new.html.erb
format.json { render json: @registry }
end
end
# GET /registries/1/edit
def edit
@registry = Registry.find(params[:id])
@user = current_user
end
# POST /registries
# POST /registries.json
def create
@registry = current_user.build_registry(params[:registry])
@user = current_user
respond_to do |format|
if @registry.save
format.html { redirect_to @registry, notice: 'Registry was successfully created.' }
format.json { render json: @registry, status: :created, location: @registry }
else
format.html { render action: "new" }
format.json { render json: @registry.errors, status: :unprocessable_entity }
end
end
end
# PUT /registries/1
# PUT /registries/1.json
def update
@registry = Registry.find(params[:id])
@user = current_user
respond_to do |format|
if @registry.update_attributes(params[:registry])
format.html { redirect_to @registry, notice: 'Registry was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @registry.errors, status: :unprocessable_entity }
end
end
end
All my Routes:
Mystorkparty::Application.routes.draw do
devise_for :users
resources :registries
root :to => "static_pages#home"
match '/home', to: 'static_pages#home'
match '/:name' => "registries#show"
When you create or update your models, you send
POST /registries
orPUT /registries/1
.But
/registries
is matched by your last rulematch '/:name' => "registries#show"
, so the request hits theshow
action.If you run
rake routes
you should see something like this:You can add
method
parameter to your route, so that it willhit
show
only onGET
request.But there are still can be collisions in the future. For example, if you have registry name
users
. So, it's commonly suggested to use prefixes (match '/r/:name'
) or define set of allowed names, or choose safe names for registries.P.S. I don't think
load_and_authorize_resource
will work for yourshow
action by default. Because it expects params[:id] to load the resource automatically.