Rails '3.2.10' .js.erb template no route matches - ruby-on-rails

In my public controller I have:
def index
#super = "test"
respond_to do |format|
format.html
format.js
end
end
I have created a index.js.erb for the index action in the views/public folder.
But when I visit http://localhost:3000/.js
I get No route matches [GET] "/.js"
This have worked before on older version of rails...

This, the very exact, question was asked here a year ago. The asker came to a conclusion, and I quote
Okay, so, I've decided that this was probably something that the Rails team did intentionally to discourage URLs like "/.atom" (because really, does that look like something that should happen?), so I'm now using a second route (get "latest", :action => :index) for the format URLs (so, like, "/latest.atom") instead.
From the question, it seems it's something happened between 3.0 and 3.1.
As a temporary solution, I still need to go deep, remove root from routes.rb and add this get "/(.:format)" instead, to: "public#index". This should work.
Edit
Yup, it could be related to this commit.
The API specifically says that root uses match to add / to the list of routes. root ends with a slash, so ... connect the dots. The commit says no format for routes end with /.
I did remove the addition (|| path.end_with?('/')) from actionpack/lib/action_dispatch/routing/mapper.rb and root can now have formats.

To make sure you don't break all the calls to the root_path helper, replace the route:
root :to => 'public#index'
With:
get '/(.:format)' => 'public#index', :as => :root

Related

route is redirecting to wrong path

This is what my routes currently look like:
which gives
On my homepage I have a create vacancy button
<%= link_to "plaats", new_employer_vacancy_path(:employer_id)%>
Which should be linked to the line from the first image
get '/employers/:employer_id/vacancies/new', to: 'vacancies#new', as: 'new_employer_vacancy'
In the vacancies_controller#new - create I have:
def new
#vacancy = Vacancy.new
#employervacancy = Employervacancy.new
end
def create
#vacancy = Vacancy.create(vacancy_params)
createEmployervacancy
redirect_to employer_vacancy_path(current_employer, #vacancy)
end
def createEmployervacancy
#employer = current_employer
Employervacancy.create(vacancy_id: #vacancy.id, employer_id: #employer.id)
end
But whenever I click the button I get redirected to some other method in my vacancies_controller that is totally irrelevant.
How is this even possible? Don't I clearly define that when that path is clicked he should go to vacancies#new? and not to vacancies#show_specific_employer_vacancies?
EDIT
After following the answers I am indeed being linked to the correct route.
First, it gave me this error.
After trying to pass the current_employer.id instead of #employer like suggested I got following error:
For your routes, you'd better to change into nested route for easily maintaining routes.
Remove these codes:
get '/employers/:employer_id/vacancies/:id', to:"vacancies#show_specific_employer_vacancies", as: "employer_vacancy"
get '/employers/:employer_id/vacancies/edit/:id' ...
get '/employers/:employer_id/vacancies/index' ...
get '/employers/:employer_id/vacancies/new' ...
path '/employers/:employer_id/vacancies/:id' ...
change into:
resources :employers do
resources :vacancies
end
Try to use basic routes here because you use standard simple form url. For example:
<%= simple_form_for(#employee, #vacancy) %>
The simple_form_for will generate url well if you use nested routes above.
Finally, in your link you have to add #employer_id
<%= link_to "plaats", new_employer_vacancy_path(:employer_id => #employer_id)%>
I hope this help you
Your router cannot tell the difference between your employer_vacancy and new_emplyer_vacancy routes because the :id parameter accepts anything. Because of this, when you point your browser to "/employers/5/vacancies/new", the route is taking your employer_vacancy route and assigning {:employer_id => 5, :id => "new"} instead of going to your new_employer_vacancy route (because routes are first-come-first-serve).
To correct this, add a constraint to your first route to ensure that only numbers (and not the string "new") is accepted into the employer_vacancy route:
get '/employers/:employer_id/vacancies/:id',
to: 'vacancies#show_specific_emplyer_vacancies',
as: 'employer_vacancy',
constraints: { id: /\d+/ } # <- This line
As Wes Foster said rails router is trying to find a first match.
It means that given a path /employers/999/vacancies/new your router looks through the routes and when it sees get '/employers/:employer_id/vacancies/:id he thinks that this route matches. So :employer_id is 999 and :id is new.
I'd suggest to put the route with :id at the end of employers routes:
...
get '/employers/:employer_id/vacancies/new'
...
get '/employers/:employer_id/vacancies/:id'
Btw this is better than adding a constraint because:
It is easier
It doesn't pollute routes file
Later you may want to change ids to be hashed or alphabetic and then you'd have to change the constraint

Custom route yields dot instead of '?id='

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!

Rails catch-all/globbing routes

I am using rails 3.0.14, and I am constructing routes.rb using the resourceful style. I'd like to have a wildcard route that catches all requests that do not match to any route stated.
What's the appropriate way to construct such a route?
put
match '*path' => 'your_controller#your_action'
at the end of the routes.rb file. This is important, since the routes are stepped through top down.
See also http://guides.rubyonrails.org/routing.html -> 3.10
For Rail 4, you need to specify the request type:
match "*path", to: "application#custom_action", via: :all
As others have said, put this at the very bottom of your routes file.
It is not mandatory to use exactly "path" in the match '*path' statement. You can set a whatever token there:
get "*string1"
or
get "*string2"
Rails will assign your real HTTP-query to the param named after your token, example:
get "*user" => "users#show"
in console:
Started GET "/john" ....
Processing by UsersController#show as HTML
Parameters: {"user"=>"john"}
You can use more than one asterisks, say get "*id*user". But in this case you will get some unpredictable result, because Rails processes 2 or more asterisks "in an intuitive way" - for more info see http://guides.rubyonrails.org/routing.html#route-globbing-and-wildcard-segments
In addition to #steel and #awenkhh, I recommend adding the following to that route's controller action
respond_to do |format|
format.html
# other formats you already support
format.all { render text: '' }
end
Otherwise, you'll wind up with some ActionView::MissingTemplate: Missing template errors for formats that you weren't expecting.
[rant]Particularly helpful for those people trying erroneous attack vectors around /wp-admin/css/wp-admin.css and the like. I seem to get about 100 requests for /wp-admin/* a day, from super annoying people who apparently would like me to get a more expensive Rollbar account plan.[/rant]

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

Rails route if no route matched

Is there a solution to redirect the user to a specific controller#action if no route matched? I had a "last rule" like this:
match ":rest" => "application#notfound", :constraints => { :rest => /.*/ }
to redirect all "other" stuff to application#notfound. The problem is that plugins with own routes where set below shis rule and never gets called.
Make a catch-all route and put it as the last rule in your routes.rb file.
match "*rest" => "application#notfound"
you also get whatever the path was as a parameter thru params[:rest] in your controller.
You are definitely not the only person having this problem. I know it's frustrating, but give it some time - I'm confident the Rails team will put together something simple and elegant. I'm in a similar position, only I need to know the incorrect url resource the user entered.
A quick Google search and I found this article demonstrating a full solution to the Rails 3.0 rescue_from ActionController::RoutingError problem. The solution involves Route Globbing and solves my need to both handle incorrect urls and capture the url entered. Hope this helps!
Put this rule last.. Routing matches from top to bottom so if it did find a match then it stops there.
Maybe it's not the best approach, but it will works while you don't find better solution
for rails 2.3, at the application controller, catch the exception like
rescue_from(ActionController::RoutingError) { redirect_to "/xpto" #add your code here }
Rails 3
At initializer put a code like:
module ActionDispatch
class ShowExceptions
def render_exception(env, exception)
if exception.kind_of? ActionController::RoutingError
render(500, 'it was routing error')
else
render(500, "some other error")
end
end
end
end
or something more clean like:
https://gist.github.com/522944
https://gist.github.com/522924
or:
match '/:anything', :to => "home#routing_error", :constraints => { :anything => /.*/ }
but maybe this last match won't be good for you as it'll override all routes from plugins/engines. I think that best solution is to use custom rack middleware for handling special cases.

Resources