Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Polymorphism and forms in Ruby on Rails

I've been full of questions lately, but thanks to this awesome community, I'm learning a ton.

I got all the help I needed with polymorphic associations earlier and now I have a question about tackling forms with polymorphic models. For instance I have Phoneable and User, so when I create my form to register a user, I want to be able to assign a few phone numbers to the user (ie: cell, work, home).

class User < ActiveRecord::Base
  has_many :phones, :as => :phoneable
end

class Phone < ActiveRecord::Base
  belongs_to :phoneable, :polymorphic => true
end

class CreateUsers < ActiveRecord::Migration
  t.column :name, :string
  t.references :phoneable, :polymorphic => true
end

class CreatePhones < ActiveRecord::Migration
  t.column :area_code, :integer
  t.column :number, :integer
  t.column :type, :string
  t.references :phoneable, :polymorphic => true
end

Now when I create my form, I'm getting confused. Normally I would do the following:

- form_for :user, :html => {:multipart => true} do |form|
  %fieldset
    %label{:for => "name"} Name:
    = form.text_field :name
    ##now how do I go about adding a phone number?
    ##typically I'd do this:
    ##%label{:for => "phone"} Phone:
    ##= form.text_field :phone

Using polymorphism, would I just approach the same way, but use fields_for?

- user_form.fields_for :phone do |phone| %>
  %label{for => "area_code"} Area Code:
  = phone.text_field :area_code
  %label{for => "number"} Number:
  = phone.text_field :number

Is this the correct approach in this instance?

like image 702
Brad Herman Avatar asked Jul 24 '10 22:07

Brad Herman


People also ask

What is polymorphism with example in Ruby?

Polymorphism is one of the fundamental features of object oriented programming, but what exactly does it mean? At its core, in Ruby, it means being able to send the same message to different objects and get different results.

Does Ruby have polymorphism?

Polymorphism works well in Ruby on Rails as an Active Record association. If models essentially do the same thing, we can turn them into one single model to create a polymorphic relationship. In this example, we have an ERD for an application where a user can post an instrument with its details.

What is single table inheritance in rails?

In Single-Table Inheritance (STI), many subclasses inherit from one superclass with all the data in the same table in the database. The superclass has a “type” column to determine which subclass an object belongs to. In a polymorphic association, one model “belongs to” several other models using a single association.


1 Answers

Before we go further, I did notice one issue - you do not need the t.references with the has_many side of the association. So you do not need it in the create_user model. What that does is it creates the phonable_id and the phoneable_type columns, you only need that in the polymorphic model.

You are heading down the correct path with the fields_for approach. But in order to get that working, you need to tell the model how to handle those fields. You do that with the accepts_nested_attributes_for class method.

class User < ActiveRecord::Base
  has_many :phones, :as => :phoneable

  accepts_nested_attributes_for :phones
end

and one minor thing, you will need to have the fields_for point to the exact name of the association

- form_for @user do |user_form|
  - user_form.fields_for :phones do |phone|

Instead of

- form_for @user do |user_form|
  - user_form.fields_for :phone do |phone|

and make sure you remove your stray %> erb tag :)

More on accepts_nested_attributes_for: http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

I hope this helps!

like image 151
Geoff Lanotte Avatar answered Oct 21 '22 21:10

Geoff Lanotte