Question

Given the following models and their associations how can I get recipes to save when their step_ingredient is an ingredient already created / saved in the database.

Currently the code below works as long as the ingredient provided does not already exist within the Ingredients table. To be clear I do not want duplicates of ingredients within my Ingredient table. I want the Step Ingredient to perform a lookup like

Ingredient.find_by_title(title: 'foo') 

I am currently not sure where in the callback chain or even which model to place to behaviour.

Recipe

class Recipe < ActiveRecord::Base

  has_many :steps
  accepts_nested_attributes_for :steps, :allow_destroy => true,
    :reject_if => lambda { |step| step[:instructions].blank? }

  validates_presence_of :name

end

Ingredient

class Ingredient < ActiveRecord::Base
  validates :title, presence: true, uniqueness: true
end

Step

class Recipe::Step < ActiveRecord::Base

  belongs_to :recipe
  has_many :step_ingredients
  has_many :ingredients, :through => :step_ingredients

  accepts_nested_attributes_for :step_ingredients

  validates_presence_of :instructions

end

Step Ingredient

class Recipe::StepIngredient < ActiveRecord::Base

  belongs_to :step
  belongs_to :ingredient

  accepts_nested_attributes_for :ingredient, :reject_if => :all_blank

  validates_numericality_of :amount, :only_integer => true, :allow_blank => true

  delegate :name, :to => :ingredient

end
Was it helpful?

Solution

Appear to have stumbled across a solution to my own question.

class Recipe::RowIngredient < ActiveRecord::Base

  belongs_to :row
  belongs_to :ingredient

  accepts_nested_attributes_for :ingredient, reject_if: :all_blank

  before_validation :get_ingredient

  def get_ingredient
    self.ingredient = Ingredient.find_or_create_by(title: ingredient.title)
  end

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