#98
Polymorphic Associations
9-17-2017
Summary
Advancing from Single Table Inheritance, learn how Polymorphic Associations differ and tricks to simplify their usage.
9
rails
model
10:31
Summary
Advancing from Single Table Inheritance, learn how Polymorphic Associations differ and tricks to simplify their usage.
9
Resources
Source - https://github.com/driftingruby/098-polymorphic-associations
Summary
Terminalrails g scaffold company name website
rails g scaffold employees first_name last_name email birth_date:date
rails g model note notable:references{polymorphic} content:textdatabase migrationsclass CreateNotes < ActiveRecord::Migration[5.1]
def change
create_table :notes do |t|
t.references :notable, polymorphic: true
t.text :content
t.timestamps
end
end
end
create_table "notes", force: :cascade do |t|
t.string "notable_type"
t.integer "notable_id"
t.text "content"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.index ["notable_type", "notable_id"], name: "index_notes_on_notable_type_and_notable_id"
endnote.rbclass Note < ApplicationRecord
belongs_to :notable, polymorphic: true
end
employee.rbclass Employee < ApplicationRecord
has_many :notes, as: :notable
endcompany.rbclass Company < ApplicationRecord
has_many :notes, as: :notable
endroutes.rbRails.application.routes.draw do
resources :companies do
resources :notes, module: :companies
end
resources :employees do
resources :notes, module: :employees
end
...
end
notes_controller.rbclass NotesController < ApplicationController
def new
@note = @notable.notes.new
end
def create
@note = @notable.notes.new note_params
@notable.save
redirect_to @notable, notice: "Your note was successfully posted."
end
private
def note_params
params.require(:note).permit(:content)
end
endemployees/notes_controller.rbclass Employees::NotesController < NotesController
before_action :set_notable
private
def set_notable
@notable = Employee.find(params[:employee_id])
end
endcompanies/notes_controller.rbclass Companies::NotesController < NotesController
before_action :set_notable
def create
# NOTIFY
super
end
private
def set_notable
@notable = Company.find(params[:company_id])
end
endemployees/show.html.erb<%= render partial: "notes/notes", locals: {notable: @employee} %>
<%= render partial: "notes/form", locals: {notable: @employee} %>companies/show.html.erb<%= render partial: "notes/notes", locals: {notable: @company} %>
<%= render partial: "notes/form", locals: {notable: @company} %>notes/_form.html.erb<%= form_with(model: [notable, Note.new], local: true) do |form| %> <div class="field"> <%= form.label :content %><br/> <%= form.text_area :content %> </div> <%= form.submit class: "btn btn-primary" %> <% end %>
notes/_notes.html.erb<h3>Notes</h3>
<% notable.notes.each do |note| %>
<p>
<hr>
<%= note.content %>
<em><%= time_ago_in_words note.created_at %></em>
</p>
<% end %>
Excellent episode, very useful.
I like it, routing via :modules is very elegant. It works for me in a normal rails application, but i can't get it work inside of a rails engine.
config/routes.rb from the engine:
Controllers:
I get the following error:
It works without specifying :modules, but this means i must place the logic in the main authorities_controller ... so its less elegant. Any idea?
Wolfgang.