Default values in join model

I have a has_many :through and I would like to take values from one side and put them in the join model. Perhaps some code would be more clear.

class Recipe < AR::Base   has_many :fermentable_ingredients   has_many :fermentables, :through => :fermentable_ingredients end

class Fermentable < AR::Base   has_many :fermentable_ingredients   has_many :recipes, :through => :fermentable_ingredients end

classFermentableIngredient < AR::Base   belongs_to :recipe   belongs_to :fermentable end

Simple enough. When I assign a fermentable to a fermentable_ingredienet, I would like to populate the fermentable_ingredient with values in fermentable. Something like this:

def fermentable=(f)   self.potential = f.potential if potential.nil?   self.color = f.color if color.nil?   super end

I know this doesn't work because the call to super fails.

Is there a clean way to do this?

Thanks, --Dean http://blog.brewsession.com/

Will this work?

class FermentableIngredient   before_save :copy_from_fermentable

  protected     def copy_from_fermentable         if self.fermentable           self.potential ||= fermentable.potential           self.color ||= fermentable.color         end     end end

Dan Manges

Thanks for the suggestion, but I want to do it before saving. Like here:

class FermentableIngredientsController < ApplicationController   def new     @fermentable_ingredient = FermentableIngredient.new     @fermentable_ingredient.fermentable = Fermentable.find( params[:fermentable_id] )     render   end end

That way the form fields for @fermentable_ingredient will be automatically filled out. As it is I have to call an extra method before render to transfer the values.

--Dean

Try this:

classFermentableIngredient < AR::Base   belongs_to :recipe   belongs_to :fermentable

  fermentable_with_copy=(f)     self.potential ||= f.potential     self.color ||= f.color     fermentable_without_copy=f   end   alias_method :fermentable_without_copy=, :fermentable=   alias_method :fermentable=, :fermentable_with_copy= end

Dan Manges

Try this:

classFermentableIngredient < AR::Base   belongs_to :recipe   belongs_to :fermentable

  fermentable_with_copy=(f)     self.potential ||= f.potential     self.color ||= f.color     fermentable_without_copy=f   end   alias_method :fermentable_without_copy=, :fermentable=   alias_method :fermentable=, :fermentable_with_copy= end

Dan Manges

That is *really* close, except it does not assign the fermentable to the ingredient.

./script/console

i = FermentableIngredient.new

=> #<FermentableIngredient...>

i.fermentable = Fermentable.find(1)

=> #<Fermentable:... "potential"=>"1.037"}>

i.potential

=> 1.037

i.fermentable.potential

NoMethodError: You have a nil object when you didn't expect it! The error occurred while evaluating nil.potential         from (irb):5

i.fermentable

=> nil

Looks like this should work from the ruby-doc on alias_method http://www.ruby-doc.org/core/classes/Module.html#M001706

  alias_method :orig_fermentable=, :fermentable=   def fermentable=(f)     self.potential ||= f.potential     self.color ||= f.color     orig_fermentable = f   end

But it still does not assign the fermentable to the fermentable_ingredient.

--Dean http://blog.brewsession.com/

And the answer is:

  alias_method :orig_fermentable=, :fermentable=

  def fermentable=(f)     self.potential ||= f.potential     self.color ||= f.color     self.orig_fermentable = f   end

Thanks to Dan for the help

--Dean http://blog.brewsession.com/