How do i customize a resourceful route in rails? - ruby-on-rails

In Rails the default path for a post 'show' action would be /post/:id.
How do I change it something like /post/:pid?
I have read about overriding the to_param method
def to_param
self.pid
end
That makes passing the pid of the post instance, but it would be available in the action as
params[:id] which is not apt.
What I would like is params[:pid] in any action would give me the pid of the post instance.
Thanks in Advance.

Try to put this in the routes:
match "/post/:pid" => "post#show"

Related

Rails- redirect_to carrying over unwanted id

I am trying to redirect from a show action to a custom collection action, but the id param is being carried over, causing the routing to fail. A minimal example:
routes.rb:
resources :first_models, only: [:show]
resources :second_models do
get 'custom_action', on: :collection
end
first_models_controller.rb
class FirstModelsController < ApplicationController
def show
redirect_to controller: 'SecondModelsController', action: 'custom_action'
end
end
second_models_controller.rb
class SecondModelsController < ApplicationController
def custom_action
# Do something
end
end
After setting that up, navigating to /first_models/2 results in an error:
No route matches {:action=>"custom_action", :controller=>"SecondModelsController", :id=>"2"}
I cannot figure out how to strip out the id param from the original request so that the routing matches.
The reason why this happens is that you call redirect_to with a Hash argument. Internally Rails uses url_for to build the final location, which in turn uses default_url_options which uses the ID of the current resource. From the API docs:
Missing routes keys may be filled in from the current request's parameters (e.g. :controller, :action, :id and any other parameters that are placed in the path).
See: http://api.rubyonrails.org/v5.1/classes/ActionDispatch/Routing/UrlFor.html
Solution: Use a named path helper.
Run bundle exec rake routes on the command line to get a list of all your routes and named path helpers. Pick the one that you need and use it as follows:
redirect_to my_named_path_helper_path
It is not the param the problem:
class FirstModelsController < ApplicationController
def show
redirect_to controller: 'second_models', action: 'custom_action'
end
end
You can type rails routes and see all your routes and how rails recognize them.
This should work. However you can be more explicit and use:
redirect_to custom_action_second_models_path

Rails form_for not working as expected

I am trying to create a small rails blog, and have run into an error. I think I've messed up the naming convention of something here... but I can't find anything specific enough to help me and give me the answer.
I have a route of
resources :blog
and a controller which has the following
class BlogController < ApplicationController
def index
#blogs = Blog.all
end
def show
#blog = Blog.find(params[:id])
end
def new
#blog = Blog.new
end
end
When I try to set up a form on the new.html.erb page, it links to routing which states
undefined method `blogs_path'
My route is blog, not blogs... where am I going wrong? I would like the route to be /blog.
Following the conventions, rename your controller file to blogs_controller.rb and the class inside of it to BlogsController. Then, in your routes.rb: resources :blogs. It should all work fine.
As already said, it should be :
resources :blogs
And I think the controller should use the plural too : BlogsController
To find what's wrong with urls you can use rake routes command
Values in first column Prefix are names of helpers you can use as prefix_url or prefix_path

Ruby on Rails - custom REST action and routing

I made custom REST action called makedefault:
class PicturesController < ApplicationController
def makedefault
...
end
end
But I get No route matches [POST] "/pictures/12" error.
In routes I've tried:
get "/pictures/:id" => "pictures#show"
But it didn't help. How can I make my own REST action and route it properly?
Since you want to create a POST route (this is what I understand from the question), you should try this:
post "/pictures/:id" => "pictures#makedefault"
The second argument after # must be pointed to your custom action.

How to route url - Ruby

I'm creating a new webpage were my users can have profile pages, and I can't seem to find the way to make a url like this:
webpage.com/profile/username
To go to my profile_controller action index and use the variable that comes on /username.
But I can't seem to find the way.
profile_controller.rb
class ProfileController < ApplicationController
def index
profile_info = Profile.find(params[:username])
end
end
And I've tried to work it around with the routes.rb but couldn't make it...
This route in your routes.rb should map get requests on /profiles/username to the index action of your profiles controller and pass the username value in params[:username]
get '/profiles/:username' => 'profiles#index'

Rails Route based on something different than ID

So currently I have something like /users/1/ when I want to view a user profile. How can I go through routes.rb to change that to /user/chiggins/ where chiggins is a unique username?
You need is to override to_param method in User model:
class User
def to_param
username
end
end
Then rails will use it automagically for routing. See http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-i-to_param
Another possibility to consider would be the friendly_id gem - https://github.com/norman/friendly_id
Nowadays there is a :param argument on the resource declaration.
http://guides.rubyonrails.org/routing.html#overriding-named-route-parameters
You can get per-resource identifier customization by redefining the member_scope and nested_scope methods on the Resource instance.
resources :users do
#scope[:scope_level_resource].tap do |u|
def u.member_scope
"#{path}/:username"
end
def u.nested_scope
"#{path}/:#{singular}_username"
# member_scope also usable here, assuming username will be nowhere in nested routes.
end
end
end
Regarding the question about #nested_scope below: It gets used when you do something like this in routing:
resources :members do
resources :playlists, only: :index
end
Then, the param would be :member_username instead of just :username. This is useful in the playlists controller when assembling the collection so you can infer the scope of the request.
The best way is to define a route with a custom param:
match "/users/:username" => "users#show"
In your controller, the plain old params[:id] will be params[:username], and you can get the user from de DB using:
User.find_by_username(params[:username])

Resources