Custom route yields dot instead of '?id=' - ruby-on-rails

I am adding a custon new action for my rails app by adding the following to my routes.rb:
resources :adventures do
member do
match :upvote, via: [:post, :delete]
match :downvote, via: [:post, :delete]
end
get 'seed', on: :new
end
(you can ignore the voting piece, just wanted to show you the whole block)
upvote_adventure POST|DELETE /adventures/:id/upvote(.:format) adventures#upvote
downvote_adventure POST|DELETE /adventures/:id/downvote(.:format) adventures#downvote
seed_new_adventure GET /adventures/new/seed(.:format) adventures#seed
adventures GET /adventures(.:format) adventures#index
POST /adventures(.:format) adventures#create
new_adventure GET /adventures/new(.:format) adventures#new
edit_adventure GET /adventures/:id/edit(.:format) adventures#edit
adventure GET /adventures/:id(.:format) adventures#show
PATCH /adventures/:id(.:format) adventures#update
PUT /adventures/:id(.:format) adventures#update
DELETE /adventures/:id(.:format) adventures#destroy
but this:
seed_new_adventure_path(#adventure_collection.id)
generates this:
http://localhost:3000/adventures/new/seed.6
instead of this:
http://localhost:3000/adventures/new/seed?id=6
I read a lot of posts with people getting dots instead of slashes, but none with adding a an additional new action. Am I doing something wrong, or do I need to add something more?
EDIT: I did make a mistake and did not mean to plurailze the adventure path (Is how I had it originally). The real problem is that all I needed to do was pass the id as a parameter.
Here is the path I was looking for:
redirect_to seed_new_adventure_path(:id => #adventure_collection.id)

It's because you are using the wrong pluralization.
In your example, you are using:
seed_new_adventures_path(#adventure_collection.id)
But the route is properly described as:
seed_new_adventure_path(#adventure_collection.id)
And will probably work fine and be more readable as:
seed_new_adventure_path(#adventure_collection)

Routes
Although Brad Werth is correct (your route pluralization is incorrect), the big problem you have is what you're trying to achieve.
You have specified the following link:
domain.com/adventure/new/seed
This is a get request with no other parameters present. I don't understand why you're passing an object to this route? This is why you're receiving the .6 problem (because Rails cannot build the routes), instead of getting /6
After thinking about what you're trying to do, and I believe you can fix it as follows:
#config/routes.rb
resources :adventures do
...
get "seed(/:id)", on: :new #-> domain.com/adventures/new/seed/6
end

OK, so in order to get this:
http://localhost:3000/adventures/new/seed?id=7
I need to pass a parameter to the link like this:
seed_new_adventure_path(:id => #adventure_collection.id)
I just forgot how to pass parameters!

Related

Nested routes in rails

I am someone who has always liked sinatra better than rails, and has never had to do a large enough scale project that rails was required (all the sources I have read say that rails is better for larger scale projects) and now I do have to do a large scale project. I have gotten very confused with the url structure of rails. What I am trying to do is the rails equivalent of this:
get "/" do
erb :index
end
get "/home" do
erb :dashboard
end
get "/home/profile" do
erb :profile
end
get "/home/friends" do
erb :friends
end
In the first one I understand that I should put in app/routes.rb I should put root home#index and in the home controller I should put def index end.
In the second one, I understand that I should do the same except replacing index with home.
But for the third and forth ones I have no idea what to do.
Also, is the a RESTful way to do the first two?
You probably want something like this
root 'home#index'
get 'home' => 'home#dashboard'
get 'home/profile' => 'home#profile'
get 'home/friends' => 'home#friends'
remember to use the command rake routes to see all your routes, where they lead and what their names are (if they have any)
I never understood what RESTful means, so someone else will have to answer that part of your question.
K M Rakibul Islam has shown you what can be called a "resourceful" way to do routes (because it uses the keyword resources) but it looks like you're just doing the static pages at this stage, so it's not necessary.
The simplest way to do routes is with this formula:
method url => controller::action, as: route_name
where method can be get, post, patch or delete so you can have different actions linked to the same URL depending on the method the request uses.
Putting a name on the route is optional, but it gives you a clean way to use the route in your views (route_name_path)
When you start making models then you'll find that using the resources keyword comes in handy. Read about it.
You can have this:
resources :home do
collection do
get :profile
end
collection do
get :friends
end
end
end
This will give you routes like this:
profile_home_index GET /home/profile(.:format) home#profile
friends_home_index GET /home/friends(.:format) home#friends
The standard way of declaring the root path:
root 'home#index'
And for the 2nd one, you have to do:
get 'home' => 'home#dashboard'
which will give you this route:
GET /home(.:format) home#dashboard
One route can be defined in many ways that works. But, Rails has conventions that should be followed while defining routes in your Rails app.
I would highly recommend you to take a look at the Rails Routing Guide

Including attributes in custom Rails routes

I hope the title is not to misleading, as I don't know a better title for the problem I'm working on:
I have a doctor which belongs to location and specialty. I'd like to route to show action of the doc controller like this:
/dentist/berlin/7
I defined my routes like this:
get ':specialty/:location/:id', to: 'docs#show'
And in my views create the following url to link to the show action of the doc controller:
<%= link_to doc.name, "#{doc.specialty.name}/#{doc.location.name}/#{doc.id}" %>
Is this a good solution to the problem? If not, is there a cleaner way to construct urls like this possibly using resources? What the heck is the name for a this problem?
Thank your very much for your help in advance.
For references, you should have a look at this page (especially the end of section 2.6)
If it is only for a single route, it's okay as you did. But then if you want to have more than one route (like /dentist/berlin/7, /dentist/berlin/7/make_appointment, etc.) you might want to structure a bit more your routes so as to take advantage of rails resources.
For example, instead of
get ':specialty/:location/:id', to: 'doctors#show'
get ':specialty/:location/:id/appointment', to: 'doctors#new_appointment'
post ':specialty/:location/:id/appointment', to: 'doctors#post_appointment'
You could have something like this (the code is almost equivalent, see explanation below)
resources :doctors, path: '/:specialty/:location', only: [:show] do
member do
get 'new_appointment'
post 'create_appointment'
end
end
Explanation
resources will generate the RESTful routes (index, show, edit, new, create, destroy) for the specified controller (doctors_controller I assume)
The 'only' means you don't want to add all the RESTful routes, just the ones specified
Then you want to add member actions, ie. actions that can be executed on a particular item of the collection. You can chose different syntaxes
resources :doctors do
member do
# Everything here will have the prefix /:id so the action applies to a particular item
end
end
# OR
resources :doctors do
get 'new_appointement', on: :member
end
By default, the controller action is the same as the path name you give, but you can also override it
member do
get 'appointment', action: 'new_appointment'
post 'appointment', action: 'post_appointment'
end
Rails has some wonderful helpers when it comes to routing !
The correct approach is to give your route a name, like this:
get ':specialty/:location/:id', to: 'docs#show', as: 'docs_show'
Then you can use it like this:
<%= link_to doc.name, docs_show_path(doc.specialty.name, doc.location.name, doc.id) %>
Note 1:
Rails appends _path at the end of the route names you define.
Note 2:
You can see all the available named routes by executing rake routes.

rails 4 routing, remove default para

I have some problem with rails 4 routing. Currently the routing is like this.
analytic_practiceday_path POST /analytics/:analytic_id/practiceday(.:format) analytics#practiceday
analytic_practiceuser_path GET /analytics/:analytic_id/practiceuser(.:format) analytics#practiceuser
I would like to have the :analytic_id part to be removed. So it will look like this
analytic_practiceday_path POST /analytics/practiceday analytics#practiceday
analytic_practiceuser_path GET /analytics/practiceuser analytics#practiceuser
My current code is
resources :analytics, :only =>"index" do
post 'practiceday', to: "analytics#practiceday"
get 'practiceuser', to: "analytics#practiceuser"
end
I know it is possible to declare it explicitly,
get '/analytic/practiceday', to: "analytics#practiceday", as: "analytic_practice_day"
But I have 20~30 routes to be defined. I would appreciate if anyone can tell me a better way to do it.
Thanks.
How about :
resources :analytics, only: :index do
collection do
post :practiceday
get :practiceuser
end
end
Try
post 'practiceday', to: "analytics#practiceday", on: :collection
Edit: This will reverse the linguistic order of your routes from analytic_practiceday_path to practiceday_analytic_path. I don't know if that's a deal breaker for you. If so, you may be forced to specify each route with :as.

Set Up Route for Accessing Private S3 Content

I've been following
https://github.com/thoughtbot/paperclip/wiki/Restricting-Access-to-Objects-Stored-on-Amazon-S3
and
Rails 3, paperclip + S3 - Howto Store for an Instance and Protect Access to try and get Paperclip's expiring links to work. I believe most of what I'm running into is one of the routing variety.
In my pieces_controller I put a method in like this
def download
redirect_to #asset.asset.expiring_url(1000)
end
And then in my routes, I put this:
match "pieces/download"
Then in my view I have:
<%= link_to download_asset_path(piece)%>
It would seem to be far from working, and I'm not sure what is messed up. I know I'm getting routing errors for one, but it's also telling me that my download_asset_path is undefined, which is likely also routing related... I feel like I'm doing everything all wrong.
Tearing my hair out. Thanks!
Try modifying your routes file to:
match 'pieces/download' => 'pieces#download', :as => 'download_asset'
Your match needs to tell which controller#action to go to, and the as option will allow you to name the route download_asset_path.
If your pieces controller is for a Piece resource it could be cleaner like:
resources :pieces do
member do
get :download
end
end
But then you would want to change the link to:
link_to 'Link text', download_piece_path(piece)
For further reading: http://guides.rubyonrails.org/routing.html

Path helpers generate paths with dots instead of slashes

In my routes.rb I have the following:
resources :message_threads
When I call:
message_threads_path(1)
I get:
/message_threads.1
Why is this? My other resources work fine. Am I not pluralizing this correctly or something?
Yes, this is a pluralization error.
By passing the ID 1, I assume that you wish to display a single record.
So you need to use the singular 'message_thread':
message_thread_path(1)
Which will yield:
http://localhost:3000/message_threads/1
Sometimes this also is when you don't provide an :as parameter in your route:
delete "delete/:id" => "home#delete"
Changed to:
delete "delete/:id" => "home#delete", as: :delete
(ignore the odd example, just happened to be something we just ran into for an internal app we're building)
Other folks that land here might be in this situation:
If you have a singular resource declared in your routes.rb:
resource :map
You don't need to pass an object to map_path. Attempting to call map_path(map) will result in similar behavior (i.e. a URL like map.12).

Resources