Question

I have two models - users and keywords and a third model associations that connects users and keywords with a has_many through relationship.

I have a create method in keyword controller that is shown below -

def create
  @keyword = Keyword.new(keyword_params)
  if Keyword.find_by(content: params[:content]).nil?
    @keyword.save
  end

  @keyword.associations.create(:user_id => current_user.id)
  flash[:success] = "Keyword successfully created!"
  redirect_to keywords_path

In the "create" method mentioned above, after a user adds a keyword, I am checking if that keyword already exists in the keywords table and if it doesn't, it saves the keyword in the keywords table and then it saves the association between user and keyword in the associations table.

However, when a keyword already exists in the keywords table (since it might have been added by another user), and lets say a new user is adding this existing keyword to his list, it gives me the error - "You cannot call create unless the parent is saved" at the @keyword.associations.create line since the @keyword.save is skipped (as the keyword already exists in the database).

I am using Rails 4 and Ruby 2.0.0

I am new to Rails and would appreciate any help you guys can provide.

Update: Adding the details of Keyword model and Keywords controller

Models: User model:

 class User < ActiveRecord::Base
      before_save { self.email = email.downcase }
      before_create :create_remember_token

      has_many :associations
      has_many :keywords, :through => :associations

      #name
      validates :name, presence: true, length: { maximum: 50 }
    end

Keyword model:

class Keyword < ActiveRecord::Base
  has_many :questions
  has_many :associations
  has_many :users, :through => :associations
  validates :content, presence: true, uniqueness: { case_sensitive: false }
end

Associations model

 class Association < ActiveRecord::Base
      belongs_to :keyword
      belongs_to :user
      validates :user_id, :uniqueness => { :scope => :keyword_id }
    end

Keywords Controller:

class KeywordsController < ApplicationController
  before_action :signed_in_user, only: [:index, :edit, :update, :destroy]

  def index
    @keywords = current_user.keywords.to_a
  end

  def new
    @keyword = Keyword.new
  end

  def create
    @keyword = Keyword.find_by(content: params[:content])
    if @keyword.nil?
      @keyword = Keyword.create(keyword_params)
    end

    @keyword.associations.create(:user_id => current_user.id)
    flash[:success] = "Keyword successfully created!"
    redirect_to keywords_path
  end

  def destroy
  end

  private
    def keyword_params
      params.require(:keyword).permit(:content)
    end
end
Was it helpful?

Solution 3

I am not sure why this works, but when I change
@keyword = Keyword.find_by(content: params[:content]) to
@keyword = Keyword.find_by(keyword_params), it works.

OTHER TIPS

That is because in the case when the Keyword is found you still refer to the Keyword.new object, which is not the one in db.

You could rewrite it like so:

def create
  @keyword = Keyword.find_by(content: params[:content])
  if @keyword.nil?
    @keyword = Keyword.create(keyword_params)
  end

  @keyword.associations.create(:user_id => current_user.id)
  flash[:success] = "Keyword successfully created!"
  redirect_to keywords_path

I think the problem could be that you are calling create in the association model (through table) instead of the user one. Rails should care about the association model not you, so just try to replace

@keyword.associations.create(:user_id => current_user.id) 

by

@keyword.users.create(:user_id => current_user.id)

If none of this works, I recommend you put a breakpoint in your controller before the create instruction and you have to see what is going on. Check out one of my recents comments about how to debug with PRY https://stackoverflow.com/a/21815636/2793607

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top