|
Feb 24, 2008
Paul Jewell
2 posts
|
Topic: Agile Web Development with Rails /
self vs. @
It doesn’t have preview, but it does allow you to edit the post. I had the same thought posting a message in a different area, but luckily spotted the edit button next to the avatar :-)
|
|
Feb 24, 2008
Paul Jewell
2 posts
|
Topic: Enterprise Integration with Ruby /
Push_with_attributes deprecation
Whilst playing with the habtm code I was informed that push_with_attributes was deprecated, and I should look to use :through instead. So, here is my effort at refreshing the code, with comments:
#! /bin/env ruby
# Model for webshop stock management example in
# Enterprise Integration with Ruby
#
# Modified to remove the deprecated push_with_attributes
# call. For more information, refer to "Agile Web Development with Rails"
# chapter 18 - sub section "Using Models as Join Tables"
require 'rubygems'
require 'active_record'
# Modify the connection details to match your setup
# - Book Reference file 5, page 34
ActiveRecord::Base.establish_connection(
:adapter => 'mysql',
:host => '127.0.0.1',
:username => 'paul',
:database => 'webshop'
)
# One change to the Bouquet class - note the reference to :through
# in the second has_many line. This allows a link to the flowers
# table via an intermediate table called ingredients
class Bouquet < ActiveRecord::Base
has_many :ingredients
has_many :flowers, :through => :ingredients
def price
ingredients.inject(self.base_price) do |total, i|
total += i.flower.price * i.quantity.to_i
end
end
# When adding flowers to the bouquet, check to see if the
# flower is already in the list - if so change the quantity
# rather than creating a new addition
# The Ingredients.new call is used as the << operator doesn't
# allow for intermediate table attributes to be set.
def add(flower,quantity)
if (ingredient = self.ingredients.find(:first,
:conditions => "flower_id = #{flower.id}"))
ingredient.quantity += quantity
ingredient.save
else
Ingredients.new(:flower_id => flower.id,
:bouquet_id => self.id,
:quantity => quantity).save!
end
end
def to_s
print "A #{self.name} costs $#{self.price} and contains #{self.flowers.size} flowers: \n"
self.ingredients.each { |i| print i.flower.name, " ", i.quantity, " off\n" }
end
end
# The link table known as bouquets_flowers is now not used. It's use is
# not recommended for cases where more detail than the link foreign keys
# are required.
#
# mysql statements to create:
# CREATE TABLE ingredients(
# id int unsigned NOT NULL auto_increment primary key,
# bouquet_id int NOT NULL,
# flower_id int NOT NULL,
# quantity int NOT NULL,
# );
#
# alter table ingredients add constraint fk1_bouquet
# foreign key (bouquet_id) references bouquets(id);
# alter table ingredients add constraint fk1_flowers
# foreign key (flower_id) references flowers(id);
class Ingredient < ActiveRecord::Base
belongs_to :flower
belongs_to :bouquet
end
# Note the reference to bouquets :through ingredients in the second
# has_many line
class Flower < ActiveRecord::Base
has_many :ingredients
has_many :bouquets, :through => :ingredients
belongs_to :stock_item
end
class StockItem < ActiveRecord::Base
has_one :flower
end
I am pretty new to ruby and ActiveRecord, and therefore would have no problem with constructive criticism :-)!
Hopefully this can clarify :through for anyone else who comes across the same issue.
Rgds., Paul
|