1

First of all, I've found some very helpful answers already (see links below), but I'm still struggling to make this work. I haven't been programming for long, and this is definitely stretching what I feel comfortable claiming to understand.

I have three models. For example's sake, I'll call them Tree, Bark, Engraving (the comments). I'm trying to add a simple form partial for users to submit new comments (engravings).

The below setup is producing the error:

NoMethodError at /trees/1 undefined method `tree' for nil:NilClass

Controllers

class TreesController < ApplicationController
  def show
   @barks = Bark.where(tree_id: @tree.id)
   @engraving= Engraving.new( :bark=> @bark)  
  end
end

class BarksController < ApplicationController
  def show
   @engravin= Engraving.new( :bark=> @bark)
   @engravings = Engraving.where(bark_id: @bark.id)  
  end
end

class EngravingsController < ApplicationController
  def show
   @bark= Bark.find(params[:bark_id])
   @engraving = Engraving.new(params[:engraving])  
  end
end

def create
@bark = Bark.find(params[:bark_id])
@engraving = Engraving.new(params[:engraving])
@engraving.user_id = current_user.id


respond_to do |format|
  if @engraving.save
    format.html { redirect_to tree_bark_path(@tree, @bark), notice: 'Comment was       successfully created.' }
    format.json { render action: 'show', status: :created, location: @engraving}
  else
    format.html { render action: 'new' }
    format.json { render json: @engraving.errors, status: :unprocessable_entity }
  end
end

end

Models

class Tree < ActiveRecord::Base
  belongs_to :user
  has_many :barks
  has_many :engravings, through: :barks
end

class Bark< ActiveRecord::Base
  belongs_to :user
  belongs_to :tree
  has_many :engravings

  delegate :title, :link, :to => :tree, :prefix => true

  def new_engraving_path
    Rails.application.routes.url_helpers.new_tree_bark_engraving_path(book, self)
  end

  def serializable_hash(*args)
    super.merge 'new_engraving_path' => new_engraving_path
  end
end

class Engraving< ActiveRecord::Base
  belongs_to :user
  belongs_to :bark

  delegate :tree, :to => :bark, :prefix => true

  def to_edit_path
    Rails.application.routes.url_helpers.edit_tree_bark_engraving_path bark_tree, bark, self
  end

  def to_path
    Rails.application.routes.url_helpers.tree_bark_engraving_path bark_tree, bark, self
  end

  def serializable_hash(*args)
    super.merge 'path' => to_path, 'edit_path' => to_edit_path
  end
end

Calling the Form in a View

On the Tree show page, I have all the Bark populating there. Clicking on an Bark element opens a modal, where the Bark.content and Engravings are shown. Under the last Engraving, I want to have a text_area form to create a new Engraving, and add it to this "piece" of bark.

# trees\show.html.erb
<%= render @barks %>

# barks\_bark.html.erb
<%= render partial: 'barks/modal', locals: { bark: bark} %>

# barks\modal.html.erb
<% render partial: '/engravings/simpleForm', :collection => bark.engravings %>

# Form partial

  <%= form_for @engraving, :url => (new_tree_bark_engraving_path(:tree_id => @bark.tree, :bark_id => @bark.id)) do |f| %>
    <%= f.hidden_field :bark_id %> 

     <div class="field">
      <%= f.text_area :content %>
     </div>

     <div class="actions">
      <%= f.submit %>
     </div>
  <% end %>

Routes

    get "pages/home"

    resources :trees do
      collection do
        get 'search'
        post 'load_from_api'
      end
    resources :barks do
      resources :engravings
    end
  end
    resources :barks do
      resources :engravings
    end

  root "trees#index"

Other Answer Sources

Rails Routing Error for nested form_for

Twice Nested Resource Form_For Issue

form_for with nested resources

Community
  • 1
  • 1

2 Answers2

1

Your error message NoMethodError at /trees/1 undefined method 'tree' for nil:NilClass means that somewhere you must be calling .tree on a nil object. The only place I can see that happening is in the form partial. I'm assuming that @bark.tree is failing.

From your question it is not clear which controller you are rendering the partial from, but the most likely cause is that @bark is not being passed into the form. Make sure that you are passing @bark into your partial, here is an example:

<%= render partial: "form", locals: {bark: @bark} %>
Tom Kadwill
  • 1,448
  • 3
  • 15
  • 21
  • Thanks! The variable is getting passed in now. – user1573016 Oct 02 '14 at 22:12
  • The form is showing multiple times now. I've checked the partial call, but it isn't that. The number of forms is the same as the number of previously submitted comments. Why would the number of comments be dictating how many forms to show? – user1573016 Oct 03 '14 at 00:14
  • The problem was the :collection in the partial call. All fixed now! – user1573016 Oct 03 '14 at 00:32
1

You're definining @barks in your trees#show action, but never @bark

def show @barks = Bark.where(tree_id: @tree.id) @engraving= Engraving.new( :bark=> @bark) end

So @bark is nil.

gdpelican
  • 568
  • 4
  • 12