aidiah aidiah - 6 months ago 15
Ruby Question

self.board.update_attributes returns undefined method `update_attributes'

During create of a reply, I'm trying to update the board's :toppid column with the line

self.board.update_attributes(:toppid => reply_max.to_i + 1)
, however this returns
NoMethodError in RepliesController#create undefined method 'update_attributes' for nil:NilClass


How can I properly update the
:toppid
column?

Rest of my code:

reply.rb:

class Reply < ActiveRecord::Base
belongs_to :board
belongs_to :post
after_create :set_pid
def set_pid
reply_max = self.post.replies.maximum(:pid)
board_max = self.board(:toppid)
if board_max.to_i > reply_max.to_i
self.update_attributes(:pid => board_max.to_i + 1)
self.board.update_attributes(:toppid => board_max.to_i + 1)
else
self.update_attributes(:pid => reply_max.to_i + 1)
self.board.update_attributes(:toppid => reply_max.to_i + 1)
end
end
end


replies_controller.rb:

class RepliesController < ApplicationController
def create
@board = Board.friendly.find(params[:board_id])
@post = @board.posts.friendly.find params[:post_id]
@reply = @post.replies.create(reply_params)
@post.touch
redirect_to @board
end
private
def reply_params
params.require(:reply).permit(:name, :email, :subject, :comment, :reply_file)
end
end


routes.rb:

resources :boards, :path => '' do
resources :posts, :path => 'thread' do
resources :replies

Answer

Take a look at your call to @reply = @post.replies.create(reply_params) your reply object never gets associated with a board object.

You probably want to use build instead. Something like:

@reply = @post.replies.build(reply_params)
@reply.board = @board
@reply.save

Edit

From your comments, there seems to be a disconnect in what you want your model relationships to be and your above code. Using belongs_to means that you have a database level foreign key relationship between one model and another.

According to your comments, you don't want this. If this is indeed the case, get rid of the relationship and delegate board to post. Otherwise, fix your tables by doing what I initially suggested and adding a board_id to your replies_table.

Here is how you would write the delegation:

class Reply < ActiveRecord::Base
  belongs_to :post
  after_create :set_pid
  delegate :board, to: :post

  def set_pid
    reply_max = self.post.replies.maximum(:pid)
    board_max = self.board(:toppid) # have no idea what you're trying to do here, but it's also a syntax error, maybe you mean to write: self.board.toppid
    if board_max.to_i > reply_max.to_i
      self.update_attributes(pid: board_max.to_i + 1)
      self.board.update_attributes(toppid: board_max.to_i + 1)
    else
      self.update_attributes(pid: reply_max.to_i + 1)
      self.board.update_attributes(toppid: reply_max.to_i + 1)
    end
  end
end

Also, assuming you have integer columns for pid and toppid (which it looks like in the update_attributes calls), your use of to_i is unnecessary.