Reputation: 4916
I have a situation where I have a SQL table which pretty much 'parents' others. It is easiest to imagine in the example below where there are different types of clients (which need different fields of data to be stored) that all have a unique client ID.
CREATE TABLE clients (
id serial NOT NULL,
internal_ref character varying,
address character varying,
telephone_no character varying,
CONSTRAINT pkey_clients PRIMARY KEY (id),
CONSTRAINT uniq_clients_internal_ref UNIQUE (internal_ref)
)
CREATE TABLE partnerships (
id serial NOT NULL,
clients_id integer,
name character varying,
CONSTRAINT pkey_partnerships PRIMARY KEY (id),
CONSTRAINT fkey_partnerships_clients_id FOREIGN KEY (clients_id)
REFERENCES clients(id) MATCH FULL
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
CREATE TABLE individuals (
id serial NOT NULL,
clients_id integer,
forename character varying,
surname character varying,
CONSTRAINT pkey_individuals PRIMARY KEY (id),
CONSTRAINT fkey_individuals_clients_id FOREIGN KEY (clients_id)
REFERENCES clients(id) MATCH FULL
ON UPDATE NO ACTION
ON DELETE NO ACTION
)
I'm new to Active Record and not sure how (or if) I can elegantly implement it, so that I can find a business and I get the joined client data.
Currently I am trying:
class Client < ActiveRecord::Base
end
class Partnership < ActiveRecord::Base
has_one :clients
end
output = Partnership.find(:all) # I only have one row in both tables, which is also joinable
p output # => [#<Partnership id: 1, name: "PART1", clients_id: 1>]
I need output
to also have the joinable data, such as internal_ref
, address
etc. How can I do that?
Upvotes: 1
Views: 149
Reputation: 6476
Easy. Your "child" models belongs_to
"parent" model which can has_one
or has_many
"children"
Models:
# app/models/client.rb
class Client < ActiveRecord::Base
has_one :partnership
has_one :individual
end
# app/models/pertnership.rb
class Partnership < ActiveRecord::Base
belongs_to :client
end
# app/models/individual.rb
class Individual < ActiveRecord::Base
belongs_to :client
end
Controller:
@output = Partnerships.all
If you don't want to make additional query each time you try to access the Client you use eager loading:
@output = Partnerships.includes(:client).all
Or eager loading with both client and individual:
@output = Partnerships.includes(:client => :individual ).all
Then, in your view, you can easily access referenced client or even individual referenced in client.
<% @output.each do |partnership| %>
<%= partneship.client.internal_ref %>
<%= partneship.client.address %>
<%= partneship.client.individual.forname %>
<% end %>
Upvotes: 3