0

I have an Opportunity model that has Activity as a nested resource. on my opportunities/show page, I have a list of activities for that opportunity and a form to add new activities. When I click "add activity" I get:

undefined method `activities' for nil:NilClass

Here is the error source:

 # POST /activities.json
  def create
    @activity = @opportunity.activities.new(activity_params)
    if @activity.save
      redirect_to @opportunity, notice: 'Activity has been added'
    else

I defined my Opportunity model as having many Activities and that my Activities belongs to an Opportunity. Here are the relevant parts of my Activity controller:

def create
  @activity = @opportunity.activities.new(activity_params)
  if @activity.save
    redirect_to @opportunity, notice: 'Activity has been added'
  else
    redirect_to @opportunity, alert: 'Unable to add Activty'
  end
end

And here is my views/activities/new code

<%= form_for ([@opportunity, @opportunity.activities.new]) do |f| %>
<div class="field">
    <%= f.label "Date Assigned" %> <br />
    <%= f.text_field :date_assigned %> 
</div>
<div class="field">
    <%= f.label "Date Due" %> <br />
    <%= f.text_field :date_due %> 
</div>
<div class="field">
    <%= f.label "Description" %> <br />
    <%= f.text_field :description %> 
</div>
<div class="field">
    <%= f.label "Status" %> <br />
    <%= f.text_field :status %> 
</div>
<div class="actions">
    <%= f.submit 'Add' %> 
</div>


<% end %>

My routes:

resources :opportunities do
   resources :activities
end

thank you!!

kiddorails
  • 12,961
  • 2
  • 32
  • 41
Trung Tran
  • 13,141
  • 42
  • 113
  • 200

2 Answers2

4

Your @opportunity is undefined(nil) in the block.

You must get @opportunity prior to building activities on it as :

@opportunity = Opportunity.find(params[:opportunity_id])

(Reason for :opportunity_id : Since this is ActivityController and your model is nested, by conventional nested RESTful resources (as specified in your routes), the parameter is automatically assigned as model_id => opportunity_id)

Changed code:

def create
  @opportunity = Opportunity.find(params[:opportunity_id])
  @activity = @opportunity.activities.new(activity_params)
  if @activity.save
    redirect_to @opportunity, notice: 'Activity has been added'
  else

Also, it is recommend to use build instead of new while building object for relations.

Community
  • 1
  • 1
kiddorails
  • 12,961
  • 2
  • 32
  • 41
  • Just curious, why do you recommend build instead of new? – Eyeslandic May 29 '14 at 21:37
  • Though, from the comments thread and further exploring, looks like `new` has now the same behavior has `build` since Rails 3.2.13 – kiddorails May 29 '14 at 21:43
  • That is an old answer, this changed in some version of Rails 3. `build` is now just an alias of `new` https://github.com/rails/rails/blob/4-0-6/activerecord/lib/active_record/relation.rb – Eyeslandic May 29 '14 at 21:44
  • 1
    @Iceman Yes, just saw that too. Thanks for the tip :) Though, I still prefer to use `build` instead of `new` in my projects; gives intuitiveness of when I am dealing with the relation objects or dealing with models directly; my personal call ;). Good to have an alternative. – kiddorails May 29 '14 at 21:48
1

Try using build instead of new.

@activities = @oportunities.activities.build(activity_params)

That should work

Edit:

You didn't find for @oportunities before the build :P

def create   
  @oportunities.find(params[:id])
  @activity = @opportunity.activities.new(activity_params)
  if @activity.save
    redirect_to @opportunity, notice: 'Activity has been added'
  else
    redirect_to @opportunity, alert: 'Unable to add Activty'
  end
end
Jorge de los Santos
  • 4,583
  • 1
  • 17
  • 35