Daniel Wernstrom Daniel Wernstrom - 1 month ago 9
Ruby Question

How to fix undefined method in nested models? post/create in Rails app

Beginner programmer, probably getting over my head with multiple models, but your help would be greatly appreciated. Subjects have many pages, pages have many sections, sections have section edits. Been searching for hours for solution, just haven't found anything that works. Why am I getting this error? I've clearly overlooked something... Thanks!

Error:

NoMethodError in SectionsController#create
NoMethodError (undefined method `subject_id' for #<Section:0x007fe2efe24a80>
Did you mean? object_id):
app/controllers/sections_controller.rb:24:in `create'


sections_controller.rb

class SectionsController < ApplicationController

layout 'admin'

before_action :confirm_logged_in
before_action :find_page
before_action :find_pages, :only => [:new, :create, :edit, :update]
before_action :set_section_count, :only => [:new, :create, :edit, :update]
...

def create
@section = Section.new(section_params)
@section.page = @page
if @section.save
flash[:notice] = "Section created successfully."
redirect_to(sections_path(:page_id => @page.id))
else
render('new')
end
end

...

private

def section_params
params.require(:section).permit(:name, :position, :visible, :content_type, :content)
end

def find_page
@page = Page.find(params[:page_id])
end

def set_section_count
@section_count = @page.sections.count
if params[:action] == 'new' || params[:action] == 'create'
@section_count += 1
end
end


with error originating from line in 'create':

if @section.save


routes.rb

Rails.application.routes.draw do

root :to => 'public#index'

get 'show/:permalink', :to => 'public#show', :as => 'public_show'

get 'admin', :to => 'access#menu'
get 'access/menu'
get 'access/login'
post 'access/attempt_login'
get 'access/logout'

resources :admin_users, :except => [:show] do
member do
get :delete
end
end

resources :subjects do
member do
get :delete
end
end

resources :pages do
member do
get :delete
end
end

resources :sections do
member do
get :delete
end
end


section.rb

class Section < ApplicationRecord

acts_as_list :scope => :subject

belongs_to :page
has_many :section_edits
has_many :admin_users, :through => :section_edits

scope :visible, lambda { where(:visible => true) }
scope :invisible, lambda { where(:visible => false) }
scope :sorted, lambda { order("position ASC") }
scope :newest_first, lambda { order("created_at DESC") }

CONTENT_TYPES = ['text', 'HTML']

validates_presence_of :name
validates_length_of :name, :maximum => 255
validates_inclusion_of :content_type, :in => CONTENT_TYPES,
:message => "must be one of: #{CONTENT_TYPES.join(', ')}"
validates_presence_of :content

end


page.rb

class Page < ApplicationRecord

acts_as_list :scope => :subject

belongs_to :subject, { :optional => false }
has_many :sections
has_and_belongs_to_many :admin_users

scope :visible, lambda { where(:visible => true) }
scope :invisible, lambda { where(:visible => false) }
scope :sorted, lambda { order("position ASC") }
scope :newest_first, lambda { order("created_at DESC") }

validates_presence_of :name
validates_length_of :name, :maximum => 255
validates_presence_of :permalink
validates_length_of :permalink, :within => 3..255
validates_uniqueness_of :permalink

end


subject.rb

class Subject < ApplicationRecord

acts_as_list

has_many :pages

scope :visible, lambda { where(:visible => true) }
scope :invisible, lambda { where(:visible => false) }
scope :sorted, lambda { order("position ASC") }
scope :newest_first, lambda { order("created_at DESC") }
scope :search, lambda {|query| where(["name LIKE ?", "%#{query}%"]) }

validates_presence_of :name
validates_length_of :name, :maximum => 255

end


Rest of my code

https://github.com/danwernstrom13/simple_cms

Let me know if I can provide any more context or code... Your assistance greatly appreciated!

Answer

You should remove this line from Section model:

acts_as_list :scope => :subject

because Section does not belong to Subject.

This would be correct:

acts_as_list :scope => :page
Comments