mjswartz
mjswartz

Reputation: 753

No route matches in Rails code

This code is all based on the Ruby on Rails tutorial by Michael Hartl. I created an assigned action in my users_controller with

def assign
  puts "in assign..."
  @scout = User.find(params[:follower_id])
  @der   = User.find(params[:followed_id])
end

I realize this doesn't do anything currently, but in the _follow partial, I have

<%= form_for @user, url: { action: "assign" } do |f| %>
  <div><%= hidden_field_tag :follower_id, @user.id %></div>
  <%= f.label :followed_id, "Assign #{@user.name} to" %>
  <%= f.collection_select :following, @ders, :id, :name, prompt: true %>
  <%= f.submit "Assign", class: "btn btn-primary" %>
<% end %>

But I'm getting the error No route matches {:action=>"assign", :controller=>"users", :id=>"4"}. I'm new to rails so this could just be a stupid question. What am I doing wrong? Do I need to modify my routes.rb file? Also, if I tried <%= form_for @user do |f| %>, how does the controller know which action to use? Is it based on the action displaying the form?

Edit: my routes.rb file is

Rails.application.routes.draw do
  root                'static_pages#home'
  get    'help'    => 'static_pages#help'
  get    'about'   => 'static_pages#about'
  get    'contact' => 'static_pages#contact'
  get    'signup'  => 'users#new'
  get    'login'   => 'sessions#new'
  post   'login'   => 'sessions#create'
  delete 'logout'  => 'sessions#destroy'
  resources :users do
    member do
      get :following, :followers
    end
  end
  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
  resources :relationships,       only: [:create, :destroy]
end

Edit 2: the HTML generated by @Rich's form_for block is

<form class="edit_user" id="edit_user_5" action="/users/5/assign" accept-charset="UTF-8" method="post">
  <input name="utf8" type="hidden" value="✓">
  <input type="hidden" name="_method" value="patch">
  <input type="hidden" name="authenticity_token" value="...">
  <label for="user_followed_id">Assign Mr. Marley Muller to</label>
  <select name="user[following]" id="user_following">
    <option value="1">Example User</option>
    <option value="2">Matthew Swartz</option>
    <option value="3">Joseph Swartz</option>
  </select>
  <input type="submit" name="commit" value="Assign" class="btn btn-primary">
</form>

Which makes sense why I'm currently getting a can't find id error since it's not sending a real id (edit_user_5)

Edit 3: Here are the parameters being passed for the request

Started PATCH "/users/6/assign" for 68.100.59.128 at 2015-12-15 03:54:39 +0000
Processing by UsersController#assign as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"...", "user"=>{"following"=>"2"}, "commit"=>"Assign", "id"=>"6"}
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 6]]
Unpermitted parameter: following
  User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", nil]]
Completed 404 Not Found in 9ms (ActiveRecord: 1.0ms)

ActiveRecord::RecordNotFound (Couldn't find User with 'id'=):
  app/controllers/users_controller.rb:69:in `assign'

Edit 4: With the following routes file,

Rails.application.routes.draw do
  root                'static_pages#home'
  get    'help'    => 'static_pages#help'
  get    'about'   => 'static_pages#about'
  get    'contact' => 'static_pages#contact'
  get    'signup'  => 'users#new'
  get    'login'   => 'sessions#new'
  post   'login'   => 'sessions#create'
  delete 'logout'  => 'sessions#destroy'
  resources :users do
    member do
      get :following, :followers
      match :assign, to: :assign, via: [:post, :patch]
    end
  end
  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
  resources :relationships,       only: [:create, :destroy]
end

and the following form for assigning one user to follow another,

<%= form_for @user, url: { action: "assign" } do |f| %>
  <%= f.label :follower_id, "Assign #{@user.name} to" %>
  <%= f.collection_select :following, @ders, :id, :name, prompt: true %>
  <%= f.submit "Assign", class: "btn btn-primary" %>
<% end %>

I am getting the ActiveRecord::RecordNotFound in UsersController#assign error of Couldn't find User with 'id'=, but with the following parameters:

{"utf8"=>"✓",
 "_method"=>"patch",
 "authenticity_token"=>"...",
 "user"=>{"following"=>"3"},
 "commit"=>"Assign",
 "id"=>"4"}

The ID's are correct: "user"=>{"following"=>"3"} and "id"=>"4", I believe I am just trying to access them incorrectly. This is the assigns action in the users controller:

def assign
  @scout = User.find(params[:id])
  @der = User.find(params_hash[:followed_id])
  # make scout follow der here
  redirect_to @scout
end

Thoughts?

Upvotes: 1

Views: 1544

Answers (3)

mjswartz
mjswartz

Reputation: 753

It turns out it was a combination of Emu and Rich's answers. The form in the HTML is

<%= form_for @user, url: { action: "assign" } do |f| %>
  <%= f.label :follower_id, "Assign #{@user.name} to" %>
  <%= f.collection_select :following, @ders, :id, :name, prompt: true %>
  <%= f.submit "Assign", class: "btn btn-primary" %>
<% end %>

With controller action

def assign
  @scout = User.find(params[:id])
  @der = User.find(params[:user][:following])
  @scout.follow(@der)
  redirect_to @scout
end

and routes as

Rails.application.routes.draw do
  root                'static_pages#home'
  get    'help'    => 'static_pages#help'
  get    'about'   => 'static_pages#about'
  get    'contact' => 'static_pages#contact'
  get    'signup'  => 'users#new'
  get    'login'   => 'sessions#new'
  post   'login'   => 'sessions#create'
  delete 'logout'  => 'sessions#destroy'
  resources :users do
    member do
      get :following, :followers
      match :assign, to: :assign, via: [:post, :patch]
    end
  end
  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
  resources :relationships,       only: [:create, :destroy]
end

Upvotes: 0

Richard Peck
Richard Peck

Reputation: 76784

To add to Emu's answer, the code you have won't work...

def assign
  puts "in assign..."
  @scout = User.find(params[:follower_id])
  @der   = User.find(params[:followed_id])
end

The params you'd get from the form_for object would be structured as:

params[:user][:follower_id]
params[:user][:followed_id]

You'd have to use the following:

#app/controllers/users_controller.rb
class UsersController < ApplicationController
   def assign
      @scout = User.find params[:id]
      @der = User.find params_hash[:followed_id]
   end

   private

   def params_hash
      params.require(:user).permit(:followed_id)
   end
end

You could also get rid of the hidden field in your form if you're using the same @user object to populate it:

<%= form_for @user, url: { action: "assign" } do |f| %>
  <%= f.label :followed_id, "Assign #{@user.name} to" %>
  <%= f.collection_select :following, @ders, :id, :name, prompt: true %>
  <%= f.submit "Assign", class: "btn btn-primary" %>
<% end %>

Update

You need to include :assign in your routes:

Rails.application.routes.draw do
  root                'static_pages#home'
  resources :static_pages, only: [], path: "" do
     collection do
        get :help, :about, :contact
     end
  end

  resources :sessions, only: [:new, :create, :destroy], path_names: {new: "login", create: "login", destroy: "logout"}

  resources :users, path_names: { new: "signup" } do
    member do
      get :following, :followers, :assign
    end
  end
  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
  resources :relationships,       only: [:create, :destroy]
end

Upvotes: 2

Emu
Emu

Reputation: 5905

In your routes.rb file you have to define the route for the specific controller action like that:

resource :users do 
  member do
    post 'assign' # change the request method to 'put'
  end
end

It will then generate a route for your assign method in the controller like: users/4/assign

For more info visit guides

Upvotes: 7

Related Questions