MaxLeoTony
MaxLeoTony

Reputation: 67

Polymorphic association: NoMethodError

NoMethodError in PostsController#create undefined method `posts' for nil:NilClass

Posts#controller

class PostsController < ApplicationController
    # before_action :logged_in_user, only: [:create, :destroy]
    before_action :correct_user,   only: :destroy
    before_action :find_postable, except: [:index]

    def index
        @posts = Post.all.order('created_at DESC')
    end

    def new
        @post = Post.new
    end

    def create
        @post = @postable.posts.new post_params 
        if @post.save
            redirect_to :back, notice: 'Your comment was successfully posted!'
        else
            redirect_to :back, notice: "Your comment wasn't posted!"
        end
    end

    def destroy
        Post.find(params[:id]).destroy
        redirect_to posts_path#, notice: "Post successfully deleted"
    end

    def edit
        @post = Post.find(params[:id])
    end

    def update
        @post = Post.find(params[:id])
        if @post.update_attributes(student_params)
            redirect_to post_path
        else 
            redirect_to edit_post_path
        end
    end

    def show
        @post = Post.find (params[:id])
    end 

    private

    def post_params
      params.require(:post).permit(:content, :image, :document, :audio, :video, :classroom_id)
    end

    def correct_user
      @post = current_user.posts.find_by(id: params[:id])
      redirect_to root_url if @post.nil?
    end

    def find_postable
      @postable = Post.find_by_id(params[:post_id]) if params[:post_id]
      @postable = Classroom.find_by_id(params[:classroom_id]) if params[:classroom_id]
    end

Here is the post model

class Post < ActiveRecord::Base
  belongs_to :user

  belongs_to :classroom

  belongs_to :postable, polymorphic: true
  has_many :posts, as: :postable
end

Here is the classroom model (it belongs to the class and this is selected in the new post form"

class Classroom < ActiveRecord::Base
  has_many :posts, as: :postable
  belongs_to :teachers
  # belongs_to :students

Posts in Schema.rb

create_table "posts", force: :cascade do |t|
    t.text     "content"
    t.integer  "user_id"
    t.datetime "created_at",            null: false
    t.datetime "updated_at",            null: false
    t.integer  "classroom_id"
    t.integer  "postable_id"
    t.string   "postable_type"
  end

I've tried many things with no success, I'm not quite sure why I'm getting this error. I'm following a video and trying to apply it to my existing post model but am still having trouble. Thanks

New Post Form:

<%= form_for :post, html: { multipart: true, class: "post-form" }, url: posts_path do |f| %>

  <h4>Choose a Classroom</h4>
  <div class="form-group">
    <%= f.collection_select :classroom_id, current_user.classrooms, :id, :name %>
  </div>
  <h4>Write a post</h4>
  <div class="form-group">
    <%= f.text_area :content, class: "form-control" %>
  </div>
  <h4>Attach Files</h4>
  <div class="form-group">
    <%= f.file_field :image %>
  </div>
  <%= f.submit "Add Post", class: "btn btn-primary" %>
<% end %>

For a post reply

<li>
  <%= post.content %> -

  <%= form_for [post, Post.new] do |f| %>
      <%= f.text_area :content, placeholder: "Add a Reply" %><br/>
      <%= f.submit "Reply"  %>
      <% end %>

</li>

Upvotes: 0

Views: 154

Answers (1)

Gerry
Gerry

Reputation: 10497

The error is in find_postable method, specifically in this line:

@postable = Classroom.find_by_id(params[:classroom_id]) if params[:classroom_id]

You are trying to fetch classroom_id from params (i.e. params[:classroom_id]) but that key (classroom_id) exists within post key in your parameters hash:

Parameters: {
  "utf7"=>"✓", 
  "authenticity_token"=>"bunchofletters==", 
  "post"=>{
    "classroom_id"=>"1",
    "content"=>"hello"
  }, 
  "commit"=>"Add Post"
}

To fix this, change params[:classroom_id] to params[:post][:classroom_id] in find_postable method:

def find_postable
  @postable = Post.find_by_id(params[:post_id]) if params[:post_id]
  @postable = Classroom.find_by_id(params[:post][:classroom_id]) if params[:classroom_id]
end

Upvotes: 1

Related Questions