user1636937 user1636937 - 4 months ago 18
Ruby Question

Undefined Method 'underscore'

I'm trying my hand at STI using Thibault's tutorial: https://samurails.com/tutorial/single-table-inheritance-with-rails-4-part-3

It's been working fine up till the dynamic paths part where I get 'undefined method `underscore' for nil:NilClass' for this snippet

def format_sti(action, type, post)
action || post ? "#{format_action(action)}#{type.underscore}" : "#{type.underscore.pluralize}"
end


Routes:

resources :blogs, controller: 'posts', type: 'Blog' do
resources :comments, except: [:index, :show]
end
resources :videos, controller: 'posts', type: 'Video'
resources :posts


Post controller:

before_action :set_post, only: [:show, :edit, :update, :destroy]
before_action :set_type
def index
@posts = type_class.all
end
...
private

def set_type
@type = type
end

def type
Post.types.include?(params[:type]) ? params[:type] : "Post"
end

def type_class
type.constantize
end

def set_post
@post = type_class.find(params[:id])
end


Posts Helper:

def sti_post_path(type = "post", post = nil, action = nil)
send "#{format_sti(action, type, post)}_path", post
end

def format_sti(action, type, post)
action || post ? "#{format_action(action)}#{type.underscore}" : "#{type.underscore.pluralize}"
end

def format_action(action)
action ? "#{action}_" : ""
end


Post index.html

<% @posts.each do |p| %>

<h2><%= p.title %></h2>
Created at: <%= p.created_at %><BR>
Created by: <%= p.user.name %><P>
<%= link_to 'Details', sti_post_path(p.type, p) %><P>
<% end %>


The error appears when I try to access index.html, and I haven't tried other links yet. I've tried removing 'underscore', then '_path' becomes an undefined method. I've also tried other suggestions such as 'gsub', but it also shows it as an undefined method, which leads me to think that it's a syntax error...

UPDATE:
I had attr_accessor :type and that made 'type' nil. So I removed that and now it is working

Answer

In your PostsHelper.rb

def format_sti(action, type, post)
    action || post ? "#{format_action(action)}#{type.underscore}" : "#{type.underscore.pluralize}"
end

This method's else portion has type.underscore. type may be nil here. To verify it, try this:

def format_sti(action, type, post)
    action || post ? "#{format_action(action)}#{type.underscore}" : "#{"post".underscore.pluralize}"
end