user2784630
user2784630

Reputation: 806

How to create a resource from link_to with no direct association?

I have 3 models called Mom, Kid and Favorite.

class Mom < ActiveRecord::Base
  has_many :kids
  has_many :favorites

class Kid < ActiveRecord::Base
  belongs_to :mom
  belongs_to :user

class Favorite < ActiveRecord::Base
  belongs_to :mom
  belongs_to :user

I'm trying to favorite a Mom in the kids/show route:

class KidsController < ApplicationController

show
 @kid = Kid.find(params[:id])
end

# link to favorite kid's mom at kids/show
link_to({ controller: 'favorites', action: 'create', id: @kid.mom.id }, { method: :post })

Now the problem I'm having is when I try to create it with this code in my favorites controller:

class FavoritesController < ApplicationController

def create
  @mom = Mom.find(params[:id])
  @favorites = current_user.favorites.build(params[:favorites])
  @favorites.mom_id = @kid.mom.id

  if @favorites.save
    redirect_to :back, notice: "#{@favorite.mom.name.titleize} is one of your favorites now."
  else
    redirect_to :back
  end
end

It throws me this error:

undefined method `mom' for nil:NilClass

Coming from this line I believe: @favorites.mom_id = @kid.mom.id

Why is this?

Upvotes: 1

Views: 71

Answers (3)

Richard Peck
Richard Peck

Reputation: 76774

Method

You've not set the @kid variable in your create class

--

When you receive no method errors, you'll typically find this is the issue:

undefined method `mom' for nil:NilClass

The error here is not the mom method, it's the nil:NilClass - you've not set @kid.

I'd do this:

def create
  @mom = Mom.find(params[:id])
  @favorites = current_user.favorites.build(favorites_params)

  if @favorites.save
    redirect_to :back, notice: "#{@favorite.mom.name.titleize} is one of your favorites now."
  else
    redirect_to :back
  end
end

private

def favorites_params
    params.require(:favorites).permit(:your, :attributes).merge(mom_id: @mom_id)
end

Upvotes: 1

user2784630
user2784630

Reputation: 806

Thanks to Baloo, Pavan and MrYoshiji I was able to get it working. Just some small changes in my create action to get everything working:

def create
  @mom = Mom.find(params[:id])
  @favorite = current_user.favorites.build(params[:favorites])
  @favorite.mom_id = @mom.id

  if @favorite.save
    redirect_to :back, notice: "#{@favorite.mom.name.titleize} is one of your favorites now."
  else
    redirect_to :back
  end
end

Upvotes: 1

jkeuhlen
jkeuhlen

Reputation: 4507

You might need to be using accepts_nested_attributes_for

Check out this railscasts

Upvotes: 1

Related Questions