Reputation: 15394
I am looking to confirm whether the following association declaration's would work of if there is a more efficient way of doing this.
I have a Animal Model and where you can create a dog, cat, rabbit etc, I also need to specify what breed the animal is, so i thought set up a model for each animal breed type, so DogBreed for example and then Cat Breed.
I was thinking that each animal can only have one breed, so would something like this work
class Animal
has_one :dog_breed
has_one :cat_breed
end
class DogBreed
belongs_to :animal
end
class CatBreed
belongs_to :animal
end
Colums for each model would be
Animal
name
description
size
breed
DogBreed
name
CatBreed
name
is there a better way to approach this?
Also i will be adding accepts_nested_attributes_for to the animal model for each breed model
Thanks
Upvotes: 2
Views: 61
Reputation: 76784
STI
You're looking for Single Table Inheritance
:
#app/models/animal.rb
class Animal < ActiveRecord::Base
has_many :x
end
#app/models/dog.rb
class Dog < Animal
end
#app/models/cat.rb
class Cat < Animal
end
As the name "Single Table Inheritance" suggests, your "dependent" models will inherit from. This means you will be able to store a central table called animals
, into which you'll need to add a type
column:
$ rails g migration AddTypeToAnimals
#db/migrate/add_type_to_animals.rb
class AddTypeToAnimals
def change
add_column :animals, :type, :string
end
end
--
Fix
The way this works is actually very simple.
You can call your Dog
and Cat
models with impunity (no changes out of the scope of "normal" Rails work). The type
column will be populated automatically:
#app/controllers/dogs_controller.b
class DogsController < ApplicationController
def new
@owner_dog = Dog.new
end
def create
@owner_dog = Dog.new dog_params
@owner_dog.save
end
private
def dog_params
params.require(:dog).permit(:x,:y,:z)
end
end
Update
From our Skype talk, you'll probably want to do this:
#app/models/animal.rb
class Animal < ActiveRecord::Base
#fields id | breed_id | name | created_at | updated_at
belongs_to :breed
delegate :name, to: :breed, prefix: true
end
#app/models/breed.rb
class Breed < ActiveRecord::Base
#fields id | name | created_at | updated_at
has_many :animals
end
This will give you the ability to use the following:
#app/controllers/animals_controller.rb
class AnimalsController < ApplicationController
def new
@animal = Animal.new
end
def create
@animal = Animal.new animal_params
end
private
def animal_params
params.require(:animal).permit(:name, :breed_id)
end
end
#app/views/animals/new.html.erb
<%= form_for @animal do |f| %>
<%= f.text_field :name %>
<%= f.collection_select :breed_id, Breed.all, :id, :name %>
<%= f.submit %>
<% end %>
Upvotes: 3