Rails single table inheritance. Shared controller, howto Update (CRUD)

crud, ruby, ruby-on-rails, sti

Solution

There is indeed a much more elegant solution. Just change your `form_for` declaration and add the `as` option, like this:

<%= form_for(@user, as: :user, url: user_path(@user), method: :put) do |f| %>

That way in your controller your parameters will be scoped under the `user` key instead of the model's class.

Problem

I've got three classes `Admin`, `Client`, `Agent` which all inherit from `User < ActiveRecord::Base`. The system is designed using STI, hence all classes share the same `users` table. I am interested in keeping the CRUD functionality pretty much the same, hence for now I am using a single `UsersController`. When implementing the Update functionality I'm faced with a doubt. Here's my edit form: ``` #Edit Form <%= form_for(@user,{url:user_path(@user),method: :put}) do |f| %> <%= render 'edit_fields',f:f %> <%= f.submit "Save", class: "btn btn-large btn-primary"%> <% end %> ``` ``` #UsersController def edit @user=User.find(params[:id]) end def update binding.pry #if @user.update_attributes(params[:user]) #<---BEFORE #WORKAROUND BELOW if @user.update_attributes(params[@user.type.downcase.to_sym]) flash[:success]="User was updated successfully." redirect_to user_path(@user) else flash[:danger]="User could not be updated." render 'new' end end ``` My "problem" is that `params` is dependent on the `@user.type` of the `@user` instance. Therefore sometimes there's a `params[:client]`, other times a `params[:admin]` or `params[:agent]`. Hence the line `if @user.update_attributes(params[:user])` does not always work. The workaround I implemented works fine, but I was wondering whether there's a more DRY or elegant way to approach these issues, i.e. sharing CRUD between different STI-ed classes.

Original source