Mike Cuddy Mike Cuddy - 5 months ago 9
Ruby Question

undefined local variable or method error-attempting to link a comment to a blog

I am working on a Rails 4 project and I currently have a comment section that is tied to a group section-the group is almost like a blog. I need the group id number to be linked to a new comment. I do not want the user to select the group id but instead have it automatically show up. I currently have this in my comment form, my problem is coming in form the last form-group with the Group Id:

<div class="form-group">
<%= form.label :author %>
<%= form.text_field :author, autofocus: true, class: "form-control",
placeholder: "Author's Name" %>
</div>

<div class="form-group">
<%= form.label :comment %>
<%= form.text_field :comment, class: "form-control", placeholder: "Write
your hearts content" %>
</div>

<div class="hide">
<%= form.number_field :user_id, value: current_user.id %>
</div>

<div class="form-group">
<%= form.number_field :group_id, value: group.id %>
</div>


What I want to do is have something like the :user_id, value: current_user.id work with each group. The user id line works fine and I have no problems with it. It is only that group line that I receive the following error: undefined local variable or method `group' for #<#:0x007f873a161fc0>

My schema looks like the following:

create_table "comments", force: :cascade do |t|
t.string "author"
t.text "comment"
t.integer "user_id"
t.integer "group_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end

create_table "groups", force: :cascade do |t|
t.string "topic"
t.integer "user_id"
t.text "description"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.float "latitude"
t.float "longitude"
t.string "address"
t.string "city"
t.string "state"
end


Finally, my comments controller looks like the following:

class CommentsController < ApplicationController

def new
@comment = Comment.new
end

def create
@comment = Comment.new(comment_params)
if @comment.save
redirect_to @group
else
render 'new'
end
end

def edit
end

def update
end

private

def comment_params
params.require(:comment).permit(:author, :comment, :user_id, :group_id)
end

end


Please let me know if any more information is needed. Thank you for the help!

Here are the models for groups and Comments:
Comment:

class Comment < ActiveRecord::Base
belongs_to :group
end


Group:

class Group < ActiveRecord::Base
has_many :collections
has_many :comments
has_many :users, :through => :collections

validates :topic, presence: true
validates :description, presence: true, length: { minimum: 10 }

geocoded_by :address
after_validation :geocode
end

Answer

Without specifying the :value option in a form_for method, Rails automatically infers the value from the column name, so leaving it out like below should work for your specific use case, otherwise instead of referring to group, use @comment.group_id:

  <div class="form-group">
    <%= form.label :author %>
    <%= form.text_field :author, autofocus: true, class: "form-control",      
      placeholder: "Author's Name" %>
  </div>

  <div class="form-group">
    <%= form.label :comment %>
    <%= form.text_field :comment, class: "form-control", placeholder: "Write  
     your hearts content" %>
  </div>

  <div class="hide">
    <%= form.number_field :user_id, value: current_user.id %>
 </div>

 <div class="form-group">
   <%= form.number_field :group_id %>
 </div>

However, I'm not totally sure whether you're approaching a few things right.

Some immediate changes, I'd probably propose would be:

Use nested routes:

# routes.rb
resources :groups do
  resources :comments
end

In your CommentsController, you could now fetch the group_id from the route:

def create
  group = Group.find(params[:group_id])
  @comment = current_user.comments.new(comment_params)
  if @comment.save 
   redirect_to @group 
  else 
   render 'new'
  end 
end

private
  def comment_params
    params.require(:comment).permit(:author, :comment)
  end

This way, in your view, you could easily do:

  <div class="form-group">
    <%= form.label :author %>
    <%= form.text_field :author, autofocus: true, class: "form-control",      
      placeholder: "Author's Name" %>
  </div>

  <div class="form-group">
    <%= form.label :comment %>
    <%= form.text_field :comment, class: "form-control", placeholder: "Write  
     your hearts content" %>
  </div>

Note: :user_id and :group_id have been removed from the form fields because those mappings are now done on the controller level.

Read more about nested routes and nested resources here