Question

I'm in need of some help regarding setting up the routing (I think that is the problem) for a view that is set up with bootstrap tabbed navigation. What I want to do is set up a form in each tab. Sounds easy enough.

However I can't figure out how the routing works when you want to submit two different actions (one to save to the db, and the other to get info from the db), each from their own tab. I can get it all to work perfectly if I give the "get_users" controller action a view, but when I try to bring it back together on the same page, just in different tabs, it goes a little awry and I'm not sure how to route correctly.

The two controller actions I have are:

class Users::RegistrationsController < Devise::RegistrationsController

    def user_accounts
        @user = User.new
    end

    def get_users
        @users = User.search(params[:search]).paginate
                (:per_page => 20, :page => params[:page] )
    end
end

EDIT ------------------------------------

Include routes.rb - excluding the extra devise related routes. Can get the create_internal_user action working not the other. I understand that the routes are incorrect as rails could never understand them. The first is correct, the second is simply what I would imagine it to look like if it were possible

# Authentication
as :user do

#add new internal users
get '/useraccounts' => 'users/registrations#user_accounts', as: 'new_internal_user'
post '/useraccounts' => 'users/registrations#create_internal_user', as: 'internal_user'

**# searching users - this is where I am uncertain**
get '/useraccounts' => 'users/registrations#get_users', as: 'get_internal_user'
post '/useraccounts' => 'users/registrations#get_users', as: 'getting_internal_user'

# other devise routes here

end

The view that renders them looks like this and renders two partials:

    <div class="container">
     <h1>User Accounts</h1>
     <ul class="nav nav-tabs">
      <li class="active"><a href="#adduser" data-toggle="tab">Add User</a></li>
      <li><a href="#getusers" data-toggle="tab">Edit User</a></li>
     </ul>
     <!-- Tab panes -->
     <div class="tab-content">
      <div class="tab-pane fade in active" id="adduser">
       <%= render 'users/registrations/create_internal' %>
     </div>
      <div class="tab-pane fade in" id="getusers">
       <%= render 'users/registrations/get_users' %>
     </div>
    </div>
   </div>

The two partials

_create_internal.html.erb

    <%= form_for(resource, as: resource_name, 
                 url: new_internal_user_path(resource_name)) do |f| %>
      <div><%= f.label :email %><br />
    <% for role in User::ROLES %>
        <%= check_box_tag "user[roles][#{role}]", role, 
                        @user.roles.include?(role), 
                        {:name => "user[roles][]"}%>

        <%= label_tag "user_roles_#{role}", role.humanize %><br />
    <% end %>
    <%= hidden_field_tag "user[roles][]", "" %>
    <div class="col-md-10 center"><%= f.submit "Create User", 
                 class: "btn btn-primary"%></div>
<% end %>

_get_users.html.erb

  <%= form_tag({:controller => "users/registrations", :action => "get_users"},
                method: :get) do %>    
<p>  
  <%= text_field_tag :search, params[:search] %>  
  <%= submit_tag "Search", :name => nil %>  
</p>
  <% end %>
  <div class="center" id="users">
  <%  if defined?(@users) %>
  <%= render 'users/registrations/searchresults' %></div>
  <%=  will_paginate @users %> 
<% end %> 

I've spent many many hours trying to figure this out and just haven't been able to. Very new to Rails so this may be an easy question for someone. I've had a look at using AJAX, and resourceful routing, but as I'm still new I'm finding it a bit tough to wrap my head around it all at the one time. This is my first post on SO so apologies if I'm missing anything (please let me know).

Was it helpful?

Solution 3

After much frustration I have solved my own problem. With help from Rich Peck I realised that I was essentially creating a view with two forms on it, and that the tabbed navigation didn't really mean anything to the problem.

So I really only needed the two routes:

# #add new internal users
get '/useraccounts' => 'users/registrations#user_accounts', as: 'user_accounts'
post '/useraccounts' => 'users/registrations#create_internal_user', as: 
                                                 'create_internal_user'

And then in the controller just changed the user_accounts action to look like this:

def user_accounts
    @user = User.new
    if params[:search_button]
        @users = User.search(params[:search]).paginate(:per_page => 15, :page => params[:page] )
    end
end

Came about this discovery thanks to this question/answer here: form_for with multiple controller actions for submit

In the end the problem wasn't what I thought it was and ended up being simple. Was certainly an interesting learning journey. Thanks for your help again Rich Peck.

OTHER TIPS

Let's say your controller is UsersController and assuming your routes are not nested, this is how you create named routes:

get '/useraccounts', to: 'users#get_users' ## this route maps to the get_users action 

post '/useraccounts' to: 'users#create_internal_user'  # this route maps to the create_internal_user action 

EDIT: the format is controller_name#action_name. So make sure to replace users with your controllers name in plural

UPDATE:

if your controller's name is RegistrationsController

try:

 get '/useraccounts', to: 'registrations#get_users'

post '/useraccounts' to: 'registrations#create_internal_user'

Looking at it, I think your error will likely be from your _get_users.html.erb partial.

Firstly, you're using form_for - why? Your use of form_for basically means you have to use the data inside @user to make it work, which I think will be causing the problem

I would use a form_tag as this does not persist your data:

<%= form_tag({:controller => "users/registrations", :action => "get_users"}, method: :get) do %>   
  <%= text_field_tag :search, params[:search] %>  
  <%= submit_tag "Search", :name => nil %>  
<% end %>

<%  if defined?(@users) #-> this might need to be passed as a local var %>
  <%= render 'users/registrations/searchresults' %></div>
  <%=  will_paginate @users %> 
<% end %> 

Routes

Your other problem is to do with your routes:

get '/useraccounts' => 'users/registrations#user_accounts', as: 'new_internal_user'
post '/useraccounts' => 'users/registrations#create_internal_user', as: 'internal_user'

**# searching users - this is where I am uncertain**
get '/useraccounts' => 'users/registrations#get_users', as: 'get_internal_user'
post '/useraccounts' => 'users/registrations#get_users', as: 'getting_internal_user'

Tell me how you expect Rails to know the difference between get '/useraccounts and get /useraccounts? The fact is it can't

You'll need to split up the routes so they don't all use the same path. I would do this:

get '/useraccounts' => 'users/registrations#user_accounts', as: 'new_internal_user'
post '/useraccounts' => 'users/registrations#create_internal_user', as: 'internal_user'

**# searching users - this is where I am uncertain**
get '/search' => 'users/registrations#get_users', as: 'get_internal_user'
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top