0

I have a controller that handles the new and edit actions for a form with a model that accepts nested attributes form another. The 'new' action works just fine. However, when I go to the edit form and submit it, it says:

Routing Error
No route matches [PATCH] "/admins/employees"

Also, when I am on the edit page it won't show all the current information there. Only the 'email' shows what is currently in the DB. Normally, the edit page shows what is currently in the DB related to those attributes, but this form is just blank, with the exception of the email. Unfortunately, googling this particular issue didn't come up with anything relevant or helpful. I think there was something close that was with Rails 3 or something but wasn't right for my problem. I am using Rails 5.1.

My code is as follows:

Employee Controller

class Admins::EmployeesController < UserActionsController
  def index
    @employees = User.where(:company => @current_company)
  end

  def edit
    @employee = User.find(params[:id])
  end

  def update
    @employee = User.find(params[:id])
    @employee.assign_attributes(employee_params)

    if @employee.save
      flash[:notice] = "Employee was updated."
      redirect_to root_path
    else
      flash.now[:alert] = "There was an error saving the information. Please try again."
      render :edit
    end
  end

  def show
    @employee = User.find(params[:id])
  end

  def new
    @employee = User.new
  end

  def create
    @employee = User.new(employee_params)
    @employee.company = @current_company

    if @employee.save
      redirect_to admins_employees_path
    else
      render :new
    end
  end

  private

  def employee_params
    params.require(:user).permit(:email, :password, :profile_attributes => [:firstName, :lastName, :title, :fullTime, :startDate])
  end
end

Edit.html.erb

<!--BODY-->
<%= render partial: 'form', locals: { employee: @employee, profile_attributes: :profile_attributes } %>
<!--BODY END-->

_form.html.erb

<%= form_for employee, url: admins_employees_path do |f| %>
  <div class="col-4 mb-3">
    <% if employee.errors.any? %>
      <div class="alert alert-danger">
        <h4><%= pluralize(employee.errors.count, "error") %>.</h4>
        <ul>
          <% employee.errors.full_messages.each do |msg| %>
            <li><%= msg %></li>
          <% end %>
        </ul>
      </div>
    <% end %>
    <div class="row">
      <div class="col p-0 mr-3">
        <div class="form-group">
          <%= f.label :email %>
          <%= f.text_field :email, class: 'form-control' %>
        </div>
        <div class="form-group">
          <%= f.label :password %>
          <%= f.text_field :password, class: 'form-control' %>
        </div>
        <%= f.fields_for profile_attributes do |user_f| %>
          <div class="form-group">
            <label>First Name</label>
            <%= user_f.text_field :firstName, :placeholder => 'First Name', class: 'form-control' %>
          </div>
          <div class="form-group">
            <label>Last Name</label>
            <%= user_f.text_field :lastName, :placeholder => 'Last Name', class: 'form-control' %>
          </div>
          <div class="form-group">
            Job <%= user_f.label :title %>
            <%= user_f.text_field :lastName, :placeholder => 'Title', class: 'form-control' %>
          </div>
          <div class="form-group">
            <label>Employment Start Date</label>
            <%= user_f.text_field :startDate, :placeholder => 'Start Date', class: 'form-control' %>
          </div>
        <% end %>
      </div>
      <div class="col-12 p-0">
        <%= f.submit "Submit", :class => 'btn btn-primary btn-block btn-lg' %>
      </div>
    </div>
  </div>
<% end %>

Thanks!

(EDIT) Routes

  Prefix Verb   URI Pattern                            Controller#Action
      employees_accounts GET    /employees/accounts(.:format)          employees/accounts#index
                         POST   /employees/accounts(.:format)          employees/accounts#create
   new_employees_account GET    /employees/accounts/new(.:format)      employees/accounts#new
  edit_employees_account GET    /employees/accounts/:id/edit(.:format) employees/accounts#edit
       employees_account GET    /employees/accounts/:id(.:format)      employees/accounts#show
                         PATCH  /employees/accounts/:id(.:format)      employees/accounts#update
                         PUT    /employees/accounts/:id(.:format)      employees/accounts#update
                         DELETE /employees/accounts/:id(.:format)      employees/accounts#destroy
         admins_accounts GET    /admins/accounts(.:format)             admins/accounts#index
                         POST   /admins/accounts(.:format)             admins/accounts#create
      new_admins_account GET    /admins/accounts/new(.:format)         admins/accounts#new
     edit_admins_account GET    /admins/accounts/:id/edit(.:format)    admins/accounts#edit
          admins_account GET    /admins/accounts/:id(.:format)         admins/accounts#show
                         PATCH  /admins/accounts/:id(.:format)         admins/accounts#update
                         PUT    /admins/accounts/:id(.:format)         admins/accounts#update
                         DELETE /admins/accounts/:id(.:format)         admins/accounts#destroy
        admins_employees GET    /admins/employees(.:format)            admins/employees#index
                         POST   /admins/employees(.:format)            admins/employees#create
     new_admins_employee GET    /admins/employees/new(.:format)        admins/employees#new
    edit_admins_employee GET    /admins/employees/:id/edit(.:format)   admins/employees#edit
         admins_employee GET    /admins/employees/:id(.:format)        admins/employees#show
                         PATCH  /admins/employees/:id(.:format)        admins/employees#update
                         PUT    /admins/employees/:id(.:format)        admins/employees#update
                         DELETE /admins/employees/:id(.:format)        admins/employees#destroy
           registrations GET    /registrations(.:format)               registrations#index
                         POST   /registrations(.:format)               registrations#create
        new_registration GET    /registrations/new(.:format)           registrations#new
       edit_registration GET    /registrations/:id/edit(.:format)      registrations#edit
            registration GET    /registrations/:id(.:format)           registrations#show
                         PATCH  /registrations/:id(.:format)           registrations#update
                         PUT    /registrations/:id(.:format)           registrations#update
                         DELETE /registrations/:id(.:format)           registrations#destroy
        new_user_session GET    /users/sign_in(.:format)               devise/sessions#new
            user_session POST   /users/sign_in(.:format)               devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)              devise/sessions#destroy
       new_user_password GET    /users/password/new(.:format)          devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format)         devise/passwords#edit
           user_password PATCH  /users/password(.:format)              devise/passwords#update
                         PUT    /users/password(.:format)              devise/passwords#update
                         POST   /users/password(.:format)              devise/passwords#create
cancel_user_registration GET    /users/cancel(.:format)                devise/registrations#cancel
   new_user_registration GET    /users/sign_up(.:format)               devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)                  devise/registrations#edit
       user_registration PATCH  /users(.:format)                       devise/registrations#update
                         PUT    /users(.:format)                       devise/registrations#update
                         DELETE /users(.:format)                       devise/registrations#destroy
                         POST   /users(.:format)                       devise/registrations#create
                    root GET    /   
Coder
  • 61
  • 9

2 Answers2

1

You can remove all this error by changing a bit in your code.

edit.html.erb :

<%= form_for employee, url: admins_employee_path(params[:id]) do |f| %>
<%= render partial: 'form', locals: { employee: @employee, profile_attributes: :profile_attributes, f: f } %>
<% end %>

new.html.erb :

<%= form_for employee, url: admins_employees_path do |f| %>
<%= render partial: 'form', locals: { employee: @employee, profile_attributes: :profile_attributes, f: f } %>
<% end %>

and remove the form line and end from form partial

Manishh
  • 1,444
  • 13
  • 23
1

for your information i would like to add that rails is so cleaver that it doesn't need to tell url with form_for , Reason being if the object in form_form is new that it will automatically hit create action on submit and if object is already exist than it will hit update action on submit. thats the beauty of partial and dry concept of rails with form_for so here

you have one partial form which is being used for edit and new action both

just change one line here:- it doesn't need to tell to url each time for new and update action.

<%= form_for employee do |f| %>
 //your codes for form
<%end%>

also there is no need to pass nested_attribites local variable, as it will automatic fetch with f object

<%= render partial: 'form', locals: { employee: @employee } %>

but for new action you would need to build nested_attribute object

  def new
    @employee = User.new
    @employee.profile_attributes.build
  end
Anand
  • 6,457
  • 3
  • 12
  • 26
  • I am curious about your answer. The answers above worked for me, though it requires alittle, very little, extra code to diff between update and new. But, if I write the code the way you show, without the url, I get this "error: undefined method `users_path' for #<#:0x007f16f1cfbd68> Did you mean? user_session_path" – Coder Jan 04 '18 at 05:43
  • @Coder are you using devise gem? – Anand Jan 04 '18 at 05:46
  • Yes, I am using the devise gem. – Coder Jan 04 '18 at 05:48
  • @Coder hmm thats why its conflicts with your `devise` routes as devise routes is also for `users` and your current routes is also for `users`. – Anand Jan 04 '18 at 05:49
  • I didn't want to do it, do you think it's better that I work within the devise registrations controller? I've done it before and it is a bit of a pain itself. But, I have exposed it before and written some custom code in it, maybe I'll explore that instead. – Coder Jan 04 '18 at 05:51
  • 1
    @Coder there is an alternative way to do this. however above concept for `fom_for` is true. alternative way to do this is make a seperate partial for `edit` action and provide it manually url to send it update action. so far as i think without provide url with form_for your new action will also not work because its routes has conflict with devise routes. – Anand Jan 04 '18 at 05:55
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/162478/discussion-between-gabbar-and-coder). – Anand Jan 04 '18 at 06:00
  • @Coder are still stuck in this issue? – Anand Jan 04 '18 at 06:47
  • I got it thanks. The other answers gave me a fix for the code and your answer pointed out where the conflict is coming from. So, at the moment I have working code, the next steps are more related to application structure. Thanks for the support. – Coder Jan 04 '18 at 06:57