0

I have a very hard time understanding why I have this issue. I looked through the majority of similar problems. In most cases authors forgot to include the relevant route. However I clearly do and I attribute this problem to gaps in my Rails knowledge which I hope some of you can address.

The error I keep getting: No route matches [GET] "/fight.29"despite having it defined in the resources :fights I also tried other methods which I commented out, but to no avail.

Few things I noticed:

  • My app tries to access http://localhost:3000/fight.29 instead of http://localhost:3000/fights/29through redirect in the FightsController
  • When I type http://localhost:3000/fights/29 manually it works perfectly fine.
  • My show action for fights is missing the prefix
  • Theres a .between fightand 29 inside url. Not sure what it means and if it has something to do with the error

Here's the output of rake routes:

            Prefix Verb   URI Pattern                                     Controller#Action
              root GET    /                                               static_pages#home
    fighter_skills GET    /fighters/:fighter_id/skills(.:format)          skills#index
                   POST   /fighters/:fighter_id/skills(.:format)          skills#create
 new_fighter_skill GET    /fighters/:fighter_id/skills/new(.:format)      skills#new
edit_fighter_skill GET    /fighters/:fighter_id/skills/:id/edit(.:format) skills#edit
     fighter_skill GET    /fighters/:fighter_id/skills/:id(.:format)      skills#show
                   PATCH  /fighters/:fighter_id/skills/:id(.:format)      skills#update
                   PUT    /fighters/:fighter_id/skills/:id(.:format)      skills#update
                   DELETE /fighters/:fighter_id/skills/:id(.:format)      skills#destroy
          fighters GET    /fighters(.:format)                             fighters#index
                   POST   /fighters(.:format)                             fighters#create
       new_fighter GET    /fighters/new(.:format)                         fighters#new
      edit_fighter GET    /fighters/:id/edit(.:format)                    fighters#edit
           fighter GET    /fighters/:id(.:format)                         fighters#show
                   PATCH  /fighters/:id(.:format)                         fighters#update
                   PUT    /fighters/:id(.:format)                         fighters#update
                   DELETE /fighters/:id(.:format)                         fighters#destroy
             fight POST   /fight(.:format)                                fights#start
         new_fight GET    /fights/new(.:format)                           fights#new
                   GET    /fights/:id(.:format)                           fights#show

Here's my routes.rb:

root 'static_pages#home'

  resources :fighters do
    resources :skills
  end
  post '/fight', to: 'fights#start'
  resources :fights, only: [:new, :show]

  #get  '/fights/:id/', to: 'fights#show'
  #match '/:id' => 'fights#show', via: [:get]

Here's the fights_controller.rb:

  def show
    @fight = Fight.find(params[:id])
  end
  def start
    @fight = Fight.create(attacker_id: params[:attacker_id], defender_id: params[:defender_id], winner: params[:winner])
    if @fight.save
      redirect_to @fight
    else
      redirect_to root_path
    end
  end

Log (another request but same error):

Started GET "/fight.30" for 127.0.0.1 at 2016-03-02 15:10:17 +0100

ActionController::RoutingError (No route matches [GET] "/fight.30"):
  actionpack (4.2.5) lib/action_dispatch/middleware/debug_exceptions.rb:21:in `call'
  web-console (2.3.0) lib/web_console/middleware.rb:28:in `block in call'
  web-console (2.3.0) lib/web_console/middleware.rb:18:in `catch'
  web-console (2.3.0) lib/web_console/middleware.rb:18:in `call'
  actionpack (4.2.5) lib/action_dispatch/middleware/show_exceptions.rb:30:in `call'
  railties (4.2.5) lib/rails/rack/logger.rb:38:in `call_app'
  railties (4.2.5) lib/rails/rack/logger.rb:20:in `block in call'
  activesupport (4.2.5) lib/active_support/tagged_logging.rb:68:in `block in tagged'
  activesupport (4.2.5) lib/active_support/tagged_logging.rb:26:in `tagged'
  activesupport (4.2.5) lib/active_support/tagged_logging.rb:68:in `tagged'
  railties (4.2.5) lib/rails/rack/logger.rb:20:in `call'
  actionpack (4.2.5) lib/action_dispatch/middleware/request_id.rb:21:in `call'
  rack (1.6.4) lib/rack/methodoverride.rb:22:in `call'
  rack (1.6.4) lib/rack/runtime.rb:18:in `call'
  activesupport (4.2.5) lib/active_support/cache/strategy/local_cache_middleware.rb:28:in `call'
  rack (1.6.4) lib/rack/lock.rb:17:in `call'
  actionpack (4.2.5) lib/action_dispatch/middleware/static.rb:116:in `call'
  rack (1.6.4) lib/rack/sendfile.rb:113:in `call'
  railties (4.2.5) lib/rails/engine.rb:518:in `call'
  railties (4.2.5) lib/rails/application.rb:165:in `call'
  rack (1.6.4) lib/rack/lock.rb:17:in `call'
  rack (1.6.4) lib/rack/content_length.rb:15:in `call'
  rack (1.6.4) lib/rack/handler/webrick.rb:88:in `service'
  /home/chrislotix/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/webrick/httpserver.rb:138:in `service'
  /home/chrislotix/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/webrick/httpserver.rb:94:in `run'
  /home/chrislotix/.rvm/rubies/ruby-2.2.1/lib/ruby/2.2.0/webrick/server.rb:294:in `block in start_thread'

What am I missing?

EDIT:

<%= link_to 'FIGHT!', fight_path(@fight, attacker_id: @attacker.id,
                                          defender_id: @defender.id,
                                          winner: compare_power_levels(@attacker, @defender)), method: :post  %>

Note: compare_power_levels simply returns one of the two objects after comparing.

Lotix
  • 309
  • 3
  • 4
  • 14

4 Answers4

2

If you are getting this issue while clicking on a link_to tag, then check your path in link_to tag.

Ideally it should look like the following:

<%= link_to 'show', fight_path(@fight) %>
dp7
  • 6,651
  • 1
  • 18
  • 37
  • I updated my comment, the issue appears after i issue a post request and then try to redirect to the fights show page. Take a look and let me know. – Lotix Mar 02 '16 at 14:29
  • What is the need of issuing a 'post' request here ? Ideally, it should be GET request and you have also defined a routes in your routes.rb as : GET /fights/:id(.:format) fights#show – dp7 Mar 02 '16 at 14:42
  • `fights_path` is a path to index action, helper does not expect any params except for optional `:format`. This will generate link to `/fights.30` – BroiSatse Mar 02 '16 at 14:42
  • @BroiSatse Yes is what I said in my answer below... That's the issue, look at his `redirect_to` – svelandiag Mar 02 '16 at 14:48
  • @SsouLlesS - you can see in his edit that he already uses `fight_path`, which means it is problem with `fight_path` url_helper defnition – BroiSatse Mar 02 '16 at 14:52
  • @BroiSatse but, he is using `method: :post` which indicates he is using the post version of the path, without that he would use the get method for the same path, I think the issue is in the `redirect_to` – svelandiag Mar 02 '16 at 14:54
  • @BroiSatse , I edited my answer from fights_path(@fight) to fight_path(@fight). Hope it will redirect user to /fights/:id path. – dp7 Mar 02 '16 at 14:55
  • @SsouLlesS - url_helpers has no idea about http verbs, they only based on route name. This is why you can POST to 'users_path', even though `users_path` in routes seems to be associated with GET. – BroiSatse Mar 02 '16 at 14:57
  • @Dinesh - It will not, look at the the output from `rake routes` - route with name `fight` is associated with template `/fight(.:format)`, no place for id there. – BroiSatse Mar 02 '16 at 14:59
  • @BroiSatse , Oh, you are pointing to the POST path , I was checking the GET path. For that user can define the followings in the routes.rb : post 'fights/:id' => 'fights#show' – dp7 Mar 02 '16 at 15:07
  • @Dinesh - Again, url_helpers don't care for the verb, they only role is to build the path. Important information is the first column, you can see there 'fight' in one raw - this is the template url_helper will use to generate `fight_path`. Normally, with pure resource it will be `/fights/:id` - you can see that route at the bottom, but it has no name which is what causing that issue. – BroiSatse Mar 02 '16 at 15:16
2

You can try

redirect_to "/fights/#{@fight.id}"

or

redirect_to fight_path(@fight)


 <%= link_to 'FIGHT!', fight_path(@fight,{ attacker_id: @attacker.id,
                                      defender_id: @defender.id,
                                      winner: compare_power_levels(@attacker, @defender)}), method: :post  %>
Pitabas Prathal
  • 1,006
  • 1
  • 12
  • 15
  • First one gives me a connection error. Second displays same error as in my initial post. – Lotix Mar 02 '16 at 14:36
1

When rails generates a link with a dot is because you are using pluralization in your path, or any other "collection" route.

You did not add your link_to so I will try to address:

<%= link_to 'show', fight_path(@fight) %>

Reference

Update

In your controller you need to redirect using the proper path:

redirect_to fight_path(@fight)
Community
  • 1
  • 1
svelandiag
  • 4,231
  • 1
  • 36
  • 72
1

The reason is here:

post '/fight', to: 'fights#start'
resources :fights, only: [:new, :show]

post '/fight' generates the named route fight_path, which normally would be created by resources. Since it is already defined, resources does not override it. You can see in your routes:

fight POST   /fight(.:format)                                fights#start

While it should be:

fight GET   /fight/:id(.:format)                                fights#start

Since route has only one optional param :format, when you call fight_path(@user), @user.id is used as a format, which results in '/fight.30'

You need to rename your post '/fight' route:

post '/fight', to: 'fights#start', :as 'start_fight'
BroiSatse
  • 44,031
  • 8
  • 61
  • 86
  • While your answer makes perfect sense and helped me understand it, the solution itself doesn't work. @pitabas prathal's first solution however solved it. I believe it might have something to do with the structure of my application. The error I'm getting after your answer is 'No route matches {:action=>"show", :attacker_id=>9, :controller=>"fights", :defender_id=>8, :id=>#, :winner=>8} missing required keys: [:id]' – Lotix Mar 02 '16 at 15:00
  • 1
    This is a good message, it is expected and it is a sign that the above worked as your Fight is not saved in your database - you cannot redirect to it. There are however quite a lot of things I am not very sure in your code. Firstly, never ever use links to send post requests - it is a serious security issue. Second thing - which action do you actually want to trigger with that link? :D – BroiSatse Mar 02 '16 at 15:10
  • That's good to hear. Whole feature of this application is very hacky right now and i believe there's a lot of room for improvement. But the rough idea is as following: I write the last two fighters inside a fight table (one labeled as attacker and other as defender, both are of fighter class) the post link is supposed to pick both fighters, determine the winner and then redirect to the show page to display the fight (the fights winner, participants etc) I based the post request on the same way i did the "Like" feature in my other project. What's the way to go? I'd love to hear your opinion. – Lotix Mar 02 '16 at 15:22