In Rails, how do you add multiple foreign keys to the same model? I have the Django equivalent
I'm using Rails 3 Beta and I assume the syntax is similar to the 2.x. I'm also not very familiar with Ruby and Rails.
In Django, multiple foreign keys to the same model looks like the following:
class Dish(models.Model):
name = models.CharField(max_length=100)
lunch = models.ForeignKey(Ingredient, related_name='lunch')
dinner = models.ForeignKey(Ingredient, related_name='dinner')
class Ingredient(models.Model):
spices = models.IntegerField()
veggies = models.IntegerField()
In Rails, I'm thinking of doing something like the following:
# Migration file
create_table :dishes do |t|
t.column :name, :string
end
create_table :ingredients do |t|
t.column :spice, :integer
t.column :veggies, :integer
t.column: :dish_id, :integer
t.column: :meal, :string # lunch or dinner
end
# Models
class Dish < ActiveRecord::Base
def lunch
return # ingredient for the current dish where type == lunch
end
def dinner
return # ingredient for the current dish where type == dinner
end
end
Is the above the right idea or is there a better way to do it?
More Clarifications: The restaurant serves the same dish during both lu开发者_StackOverflow社区nch and dinner but uses different amount of ingredient between those two meal times. Each dish can contain at most one lunch ingredient object and at most one dinner ingredient object.
Its not clear from your model if there is a 1-to-1
or 1-to-n
relationship amongst Dish
model and Ingredients
model.
If the relationship is 1-to-1
, following code should work:
class Dish < ActiveRecord::Base
has_one :lunch, :class_name => 'Ingredient', :conditions => {:meal => 'lunch'}
has_one :dinnner, :class_name => 'Ingredient', :conditions => {:meal => 'dinner'}
end
# now you can get lunch and dinner using the calls below on a Dish object.
dish.lunch
dish.lunch
If the relationship is 1-to-n
, following code should work:
class Dish < ActiveRecord::Base
has_many :lunches, :class_name => 'Ingredient', :conditions => {:meal => 'lunch'}
has_many :dinnners, :class_name => 'Ingredient', :conditions => {:meal => 'dinner'}
end
Firstly for me it doesn't look good if you use string column to store only two types of something. You can store it as boolean or as integer when there are more types of meals. You can add an array that maps meal type id to lunch
or dinner
or anything else.
# Ingredient model
belongs_to :dish
def meal
MEAL_TYPES[meal_id]
end
private
MEAL_TYPES = ['lunch', 'dinner']
# Dish model
has_one :lunch, :class_name => 'Ingredient', :conditions => {:meal_id => 0}
has_one :dinner, :class_name => 'Ingredient', :conditions => {:meal_id => 1}
Then in your code you can use it as fallows:
@dish = Dish.find(params[:id])
@dish.lunch # returns lunch ingredients
@dish.dinner # returns dinner ingredients
@dish.lunch.meal # => "lunch"
精彩评论