TLDR; I need to have my new_topic_post_path link to /tennis/publish instead of /tennis/new
I have defined a custom route in routes.rb:
match '/:topic_id/publish', to: 'posts#new', via: [:get, :post]
But still new_topic_post_path(topic) returns a link:
http://localhost:3000/tennis/new
However, for cosmetical reasons I need the url to look like this:
http://localhost:3000/tennis/publish
Any ideas? Big appreciations for any answers. Thanks in advance.
(Also... if that is not possible, is there any way to add string in link_to, such as: link_to post.name, post(/publish) to achieve similar result? I tried countless variations of that, but couldn't find a way.)
Edit: Also, I'm having the links in
<% all_topics.sort { |a,b| a.name <=> b.name }.each do |topic| %>
<%= link_to topic.name, new_topic_post_path(topic) %>
<% end %>
So straight link_to "tennis/publish isn't suitable.
match '/:topic_id/publish', to: 'posts#new', via: [:get, :post], as: publish_topic
Then use publish_topic_path route helper.
Also you can do:
resources :posts, path_names: { new: 'publish' }
Try this...
resources :tennis, path_names: { new: 'publish' }
I'm not sure how to do it for all, though.
You need to take advantage of the :as option, which is used to generate routing helpers, in your routes.rb file, like so:
match '/:topic_id/publish', to: 'posts#new', via: [:get, :post], as: 'new_topic_post'
You can read more about options for the #match method here: http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Base.html#method-i-match
Related
I have written freindly URLs for the show action of the School Resource but now have
before i had ;
http://webaddress/schools/2
and now i have;
http://webaddress/schools/school_name
However, i want
http://webaddress/school_name
My config routes look like this for the resource;
resources :schools do
collection do
match 'search' => 'schools#search', via: [:get, :post], as: :search
end
end
How can i achieve that? thank you
Add this at the last your routes file:
match ':id' => 'schools#show', via: [:get]
A more conventional way would be to use the path: option in your route resources, like this:
#config/routes.rb
...
resources :schools, path: "", only: :show #-> has to go at end of file!
This will give you the ability to add different methods to this, as well as keeping with Rails conventions :)
I have a search scope for my users with the following route:
resources :users do
collection do
get :search
end
end
This however generates /users/search as url. I would like to have /search as url. I tried the following:
get '/search', as: :search
get '/search' => 'users#search', as: :search
get :search, to: 'users#search', as: :search
They don't seem to work since I keep getting routing errors. What would be the correct way to write it?
This one should work (without the leading '/') :
resources :users
get 'search' => 'users#search', as: :search
The named helpers for this route will be search_path and search_url
you can also use match:
match "/search", to: "users#search", via: "get"
Here is my link_to
<%= link_to sub_category.name, controller: :posts, action: :product, id: "#{sub_category.slug}-#{sub_category.id}" %>
Which is pointing to the url
http://localhost:3000/posts/product/fifith-category-s-sub-category-2
I need the url as follows
http://localhost:3000/fifith-category-s-sub-category-2
How can i do it.
my route.rb
resources :posts
match ':controller(/:action(/:id))(.:format)', via: [:get,:post]
what #MarekLipka suggests is correct but defining your routes like this will take up all the single level namespace in your app i.e. "/anything" will route by default to posts#product.
I recommended using some form of identifier to figure out which routes should go to posts#product. What will work for you depends on why you want to do this. Couple of options are:
Use a short namespace:
scope '/pp' do
get ':id', to: 'posts#product
end
# "/pp/:id" routes to 'posts/product'
# pp is a random short name I picked, it could be anything
# link
<%= link_to sub_category.name, "pp/#{sub_category.slug}-#{sub_category.id}" %>
Use a constraint:
get ':id', to: 'posts#product`, constraints: { :id => /sub\-category/ }
# only id's with 'sub-cateogry' route to 'posts/product'
# link (assuming that sub_category.slug has 'sub-category' words in it)
<%= link_to sub_category.name, "#{sub_category.slug}-#{sub_category.id}" %>
If you want path /:id match your posts#product, you should have something like this in your routes:
resources :posts
match ':id', to: 'posts#product`, via: :get
match ':controller(/:action(/:id))(.:format)', via: [:get, :post]
I'm trying to setup a route that looks like this: acme.com/posts/:category/:status. Both :category and :status are optional. I wrote many variations, but none worked:
resources :posts do
match '(/:category)(/:status)', to: 'posts#index', as: 'filter', on: :collection
end
# Category Links
link_to "Questions", filter_posts_path(:questions)
link_to "Suggestions", filter_posts_path(:suggestions)
# Status Links
link_to "Published", filter_posts_path(params[:category], :published)
link_to "Draft", filter_posts_path(params[:category], :draft)
The idea is to be able to 1) filter by category, 2) filter by status, and 3) filter by both category and status if both are available. The current setup has also broken my /posts/new path, always redirecting to posts#index.
I had this variation and it seems working fine:
namespace :admin do
resources :posts, :except => [:show] do
collection do
get "/(:category(/:status))", to: "posts#index", as: "list", :constraints => lambda{|req|
req.env["PATH_INFO"].to_s !~ /new|\d/i
}
end
end
end
= CONTROLLER=admin/posts rake route
list_admin_posts GET /admin/posts(/:category(/:status))(.:format) admin/posts#index
You can use the more RESTful resources :posts (in config/routes.rb) and send the params in the query string.
With that approach, all parameters are optional and you're not limited to using predefined parameters.
Do this works for you?
resources :posts do
collection do
match '/:category(/:status)', to: 'posts#index', as: 'filter'
match '/:status', to: 'posts#index', as: 'filter'
end
end
Hope at least it helps!
You could try something like this:
match '/filter/*category_or_status' => 'posts#index', as: 'filter'
With this you can build your own filter path. Then you could parse params[:category_or_status] in your controller and get the category or status if they are given.
In config/routes.rb, I tried both:
root :to => 'things#index', :as => 'things'
and
root :to => 'things#index'
When I hit http://localhost:3000/, both approaches work, and nothing seems to be different.
What is the :as option used for?
The :as option forms a named route.
Usually it's used in a non-root route. For example:
match '/search' => 'search#search', :as => 'search' # SearchController#search
You could then do something like:
<%= link_to search_path, 'Click Here to Search!' %>
search_path and search_url are defined because of the :as
For a root route, you don't really need :as because the the URL helpers root_path and root_url are defined for you by Rails.
Rails 4 compatible.
In path_to_your_app/config/routes.rb
get "/profile/edit" => "users#profile_edit", :as => "edit_me"
Since ruby 2.0 you can use:
get "/profile/edit", to: "users#profile_edit", as: "edit_me"
In path_to_your_app/app/views/**in required view
<%= link_to "Edit profile", edit_me_path %>
Do not use match if you aren't sure you need it:
It creates a vulnerability when you use it in next pattern:
match ':controller/:action/:id'
From documentation:
You should not use the match method in your router without
specifying an HTTP method. If you want to expose your action to both
GET and POST, add via: [:get, :post] option. If you want to expose
your action to GET, use get in the router:
Instead of: match "controller#action"
Do: get "controller#action"
Read more about:
About match
http://github.com/rails/rails/issues/5964
About routes mapping
http://apidock.com/rails/v4.0.2/ActionDispatch/Routing/Mapper/Base/match
http://api.rubyonrails.org/classes/ActionDispatch/Routing/Mapper/Base.html
About routes in general
http://api.rubyonrails.org/classes/ActionDispatch/Routing.html
The :as option creates a named path. You can then call this path in your controllers and views (e.g. redirect_to things_path). This isn't very useful for the root path (as it already named root), but is very useful for new routes you add.