Ifeanyi Kalu
Ifeanyi Kalu

Reputation: 55

How can I implement a 'create' action without 'new' action

How can I best implement this feature: As an admin, I can assign a Resident Manager to a Hall.

I know implementing the above feature, entails creating a new record in the management table but I don't know how to do it. I didn't think using a form (management#new) would solve this because the admin should not know the user_ids/hall_ids...

BELOW IS WHAT I HAVE TRIED TO DO BUT I CAN'T GET IT RIGHT

When the admin gets to the user index page, s/he should see a link for Hall Assignment for each user. This link leads to the management show page for that particular user, which would show the list of halls assigned to that user and also the show all the other remaining halls that isn't assigned to the user. So, either clicking an ADD button or on the hall's name should add it to that user's assigned halls list which is on the same page.

Management#show page

<h2><%= @user.email %>'s assigned halls</h2>

<% @user.managements.each do |management| %>
  <%= management.hall.name %>
<% end %>

<p> HALL LISTS </p>

<ul>
  <% @halls.each do |hall| %>
    <li><%= hall.name %> <%= button_to "Add" %> </li>
  <% end %>
</ul>

Here's is my Management controller

class Admin::ManagementsController < ApplicationController
  def index
    @managements = Management.all
  end

  def show
    @user = User.find(params[:id])
    @halls = Hall.all
  end

  def create
    @management = Management.create(managements_params)

    redirect_to admin_management_path
  end

  private 

  def managements_params 
    params.
      require(:management).
      permit(user_id: params[:user_id], hall_id: params[:hall_id])
  end
end

And here's a piece of what my routes file looks like:

 namespace :admin do
   resources :users, only: [:index, :update]
   resources :halls, only: [:index, :new, :create]
   resources :managements, only: [:index, :new, :create, :show] do
     resources :halls, only: [:index]
   end
 end

Upvotes: 3

Views: 1858

Answers (2)

Richard Peck
Richard Peck

Reputation: 76774

First things first -

How can I implement a 'create' action without 'new' action

It's relatively simple to do - you will need a create action somewhere, but a new action is just a way to build the respective ActiveRecord object for your controller.

If you do this in another action, you just have to make sure you point the form to the correct create action (and that create action to redirect back to

--

New / Create

Here's how you could handle the new / create actions in different controllers, as an example for you:

#app/controllers/users_controller.rb
Class UsersController < ApplicationController
   def index
      @hall = Hall.new
   end
end

#app/controllers/halls_controller.rb
Class HallsController < ApplicationController
    def create
       @hall = Hall.new hall_params
       redirect_to users_path if @hall.save
    end

    private

    def hall_params
       params.require(:hall).(:hall, :attributes, :user_id)
    end
end

This will allow you to show the following:

#app/views/users/index.html.erb
<% @users.each do |user| %>
   <%= link_to user.name, user %>

   <%= form_for @hall, url: hall_path do |f| %>
      <%= f.hidden_field :user_id, value: user.id %>
      <%= f.text_field :x %>
      <%= f.submit %>
   <% end %>
<% end %>

--

Fix

ADD button or on the hall's name should add it to that user's assigned halls list

For this, I don't think you'd need a create action in the "traditional" sense - it will be more about adding new halls to a user's current halls. This is much different than creating a new hall itself:

#config/routes.rb
namespace :admin do
   resources :users do
      post "hall/:id", to: :add_all #=> domain.com/admin/users/:user_id/hall/:id
   end
end

#app/controllers/admin/users_controller.rb
Class UsersController < ApplicationController
   def add_hall
      @user = User.find params[:user_id]
      @hall = Hall.find params[:id]

      @user.halls << @hall
   end
end

#app/models/user.rb
Class User < ActiveRecord::Base
   has_many :user_halls
   has_many :halls, through: :user_halls
end

#app/models/hall.rb
Class Hall < ActiveRecord::Base
   has_many :user_halls
   has_many :users, through: :user_halls
end

#app/models/user_hall.rb
Class UserHall < ActiveRecord::Base
   belongs_to :user
   belongs_to :hall
end

This uses the ActiveRecord collection methods to make this work, to which you'll be able to provide the following:

#app/views/users/index.html.erb
<% @users.each do |user| %>
   <%= link_to user.name, user %>
   <%= button_to "Add Hall Test", user_add_hall_path(user, 1) %>
<% end %> 

Upvotes: 2

Taryn East
Taryn East

Reputation: 27747

Your "add" button is just a mini form (with mostly hidden fields). You can instead just make it an actual form (with the submit-button having the text "Add") and the id-values filled in from the item on the page... it just points to the same routes that you'd normally point the form that you'd find in the new template.

if you want more detail, then show us the code that you have written (rather than a verbal description of it).

Edit:

Ok, so you'd put a button on the page like this

<ul>
  <% @halls.each do |hall| %>
    <li><%= hall.name %> <%= button_to "Add", managements_path(management: {user_id: @user.id, hall_id: hall.id}, method: :put ) %> </li>
  <% end %>
</ul>

Notice the managements_path - you might need to check that that routing is correct (check it against what is in rake routes). Note that you're passing in the user id and the hall id, and that you must set the method to "put" on the button.

Upvotes: 4

Related Questions