Ruby On Rails: How to use find with the has_one relationship - sql

I have two models A and B where:
A has_one B
I therefore have added a foreign key to A that associates every instance of A with the id of an instance of B. Note that I do know want this to be a 1-1 relationship.
How can I use A.find() to get all the instances of A that are associated with an instance of B with a certain attribute from B (B.name for example)?
I know that this can be done with a SQL join between the two tables but is there an elegant way of doing this in ROR?

Assuming you have the right associations setup:
time_range = (Time.now.midnight - 1.day)..Time.now.midnight
Client.joins(:orders).where(:orders => {:created_at => time_range})
This is from the Active Record Querying guide

has_one association requires foreign key in belonging model.
Please take a look on RailsGuides - http://guides.rubyonrails.org/association_basics.html#the-has_one-association

Related

Rails Model association with tabless Model

I want to perform has_one, belongs_to association on a tableless model.
class A < ActiveRecord::Base
has_one: b
end
class B < Tableless
attr_accessor: b
end
I want to know whether this is possible in Rails
Can you define an association on a tableless model? I'm going to answer 'no'. Associations use foreign keys to retrieve associated records and without a table to store that foreign key you cannot retrieve that record.
Documentation about association methods.

active record recursive many-to-many association

I want to set up a many-to-many recursive association with the model Projects
a Project has_many Comps (or comparables), which are other Projects
and a Project can be the Comp of many Projects
I'd like to add other columns to each record, so I need a join table
I've done the following research which has not helped:
This article is a clear basic explanation of sql recursive associations, but there is no specifics on activerecord implementation
this stack overflow article deals with a one-to-many relationship,
and not a many-to-many
I tried this rails method of setting up what seems to be multiple
join tables, but it is confusing and did not work for me.
I tried this rails method and it did not work for me, maybe because it assigns primary keys to two columns in a table, which I did not do
In the last link, here is the code in question:
CREATE TABLE tutorship (
tutor_id INTEGER,
tutored_id INTEGER,
hasPaid BOOLEAN,
PRIMARY KEY (tutor_id, tutored_id)
);
how can you have two primary keys in the same table? If that is correct, is this the issue, and how do i set this up?
Generally, how do i set this up in active record?
The term you are looking for seems to be "self referential many to many join".
It's tricky to get right the first time definitely reccomend testing and retesting your associations in rails console as you build this out.
rails many to many self join
http://railscasts.com/episodes/163-self-referential-association?view=comments
```
class Project < ActiveRecord::Base
has_many :comparables
has_many :comps, :through => :comparables
# rest of class omitted.
end
class Comparables < ActiveRecord::Base
belongs_to :project
belongs_to :comp, :class_name => 'Project'
end
```
someone correct me if I err'd in the example above.
You can't have more than 1 primary key. By the very definition this doesn't make sense. You can have more than 1 unique index though. What you are describing is NOT recursive. It is a many to many relationship. I don't quite understand what you really want here because you have some code that talks about tutors but your original comment had to to with projects.
Let's say you have Projects. And any given project can have multiple comps. At the same time any given comp can be associated with more than 1 project. The way you do this is with a union table.
Something along these lines.
create table Projects
(
ProjectID int,
OtherColumnsHere
)
create table Comps
(
CompID int,
OtherColumnsHere
)
create table ProjectComps
(
ProjectID int,
CompID int,
AuditingColumnsLikeDateCreatedHere
)

Rails Model class relations in ternary many-many case

I have a 'users' table, 'groups' table and 'invitations' table(join table). I am trying to build a relation between 'invitors'(class_name 'User'), 'invitees'(class_name 'User') and 'groups'(class_name 'Group') where 'invitations'(class_name 'Invitation') is the join table with foreign keys 'invitor_id', 'invitee_id' and 'group_id'.
(Many 'Invitors' can give 'Invitations' to Many 'Invitees' to join Many 'Groups')
I tried several ways by explicitly specifying :foreign_key and :class_name in my Model classes, but in vain. I have just started learning the 'activerecord relations' concepts in rails, and i really want to make efficient use of it. Can someone help me out with this problem.
The problem you are trying to solve here, in ActiveRecord terms, is a "self referential" association. Ryan Bates provides a great example that answers your situation almost exactly:
http://railscasts.com/episodes/163-self-referential-association
In his example you can replace "Friendship" with your idea of an "Invitation". You will need to add a group_id to his Friendship model to keep track of which Group the Invitation is related to.

rails3 and the proper way to use associations

I'm doing my first rails(3) application.
Associations don't make sense. First, even the rails guides don't
really explain what they do, they just explain how to use them.
From what I gather, associations do two things:
a) Allow ActiveRecord to optimize the structure of the database.
b) Allow ActiveRecord to offer an alternate ruby syntax for
joins and the like (SQL queries). I want this.
I'm trying to understand associations, and how to properly use them. Based
on the example below, it seems like associations are 'broken' or at least
the documentation is.
Consider a trivial version of my application. A teacher modifying wordlists
for study.
There are 3 relevant tables for this discussion. For clarity, I've simply
included the annotate(1) tool's definition of the table, and removed
unnecessary fields/columns.
A wordlist management table:
Table name: wordlist_mgmnt_records
id :integer not null, primary key
byline_id :integer(8) not null
A table that maps words to a word list:
Table name: wordlists
wordlist_mgmnt_id :integer not null
word_id :integer not null
We don't actually care about the words themselves. But we do care about
the last table, the bylines:
Table name: bylines
id :integer(8) not null, primary key
teacher_id :integer not null
comment :text not null
Bylines record who, what tool was used, where, when, etc. Bylines are
mainly used to trouble shoot what happened so I can explain to users what
they should have done (and/or repair their mistakes).
A teacher may modify one or more word list management records at a time
(aka single byline). Said another way, a single change may update multiple
word lists.
For wordlist_mgmnt_records the associations would be:
has_many :bylines # the same byline id can exist
# in many wordlist_mgmnt_records
But what's the corresponding entry for bylines?
The Beginning Rails 3 (Carneiro, et al) book says:
"Note: For has_one and has_many associations, adding a belongs_to
on the other side of the association is always recommended. The
rule of thumb is that the belongs_to declaration always goes in
the class with the foreign key."
[ Yes, I've also looked at the online rails guide(s) for this. Didn't
help. ]
For the bylines table/class do I really want to say?
belongs_to :wordlist_mgmnt_records
That really doesn't make sense. the bylines table basically belongs_to
every table in the data base with a bylines_id. So would I really say
belongs_to all of them? Wouldn't that set up foreign keys in all of the
other tables? That in turn would make changes more expensive (too many
CPU cycles) than I really want. Some changes hit lots of tables, some of
them very large. I prize speed in normal use, and am willing to wait to
find bylines without foreign keys when using bylines for cleanup/repair.
Which brings us full circle. What are associations really doing in rails,
and how does one use them intelligently?
Just using associations because you can doesn't seem to be the right
answer, but how do you get the added join syntax otherwise?
I'll try to help your confusion....
A byline can have multiple wordlist_mgmnt_records, so defining the has_many there seems to make sense.
I'm not sure I understand your confusion in the other direction. Since you have defined the attribute wordlist_mgmnt_records.byline_id, any given wordlist_mgmnt_record can only 'have' (belong_to) a single byline. You're simply defining the crows foot via ruby (if you like database diagrams):
wordlist_msgmnt_records (many)>>----------(one) byline
Or read in english: "One byline can have many wordlist_mgmnts, and many individual wordlist_mgmnt's can belong to a single byline"
Adding the belongs_to definition to the wordlist_mgmnt model doesn't affect the performance of the queries, it just let's you do things like:
#record = WordlistMgmntRecord.find(8)
#record_byline = #record.byline
Additionally you're able to do joins on tables like:
#records = WordlistMgmntRecord.joins(:byline).where({:byline => {:teacher_id => current_user.id}})
Which will execute this SQL:
SELECT wordlist_mgmnt_records.*
FROM wordlist_mgmnt_records
INNER JOIN bylines
ON wordlist_mgmnt_records.byline_id = bylines.id
WHERE bylines.teacher_id = 25
(Assuming current_user.id returned 25)
This is based off of your current DB design. If you find that there's a way you can implement the functionality you want without having byline_id as a foreign key in the wordlist_mgmnt_records table then you would modify your models to accomodate it. However this seems to be how a normalized database should look, and I'm not really sure what other way you would do it.

Ruby on Rails: joining two tables on something other than the standard foreign key

I have a rails query like:
#user = User.find_by_username(params[:search], :include => [:user_similars])
Models: user (has_many :user_similars), user_similar (belongs_to :user)
The user_similars mysql table has a "user_id" field as a foreign key, but I don't want :include to join on that for this instance. I'd like to join on another field called "user_id_similar"
Is there a parameter to change the way :include behaves so it can join on another field?
Or should I be using :join with a different option?
Or maybe edit the model method declarations?
Thanks!
Thanks Toby! In the user model user I added:
has_many :user_similars, :foreign_key => "user_id_similar"
and this solved it.
When you define the relationship between the two tables, you can specify which column to use as the Foreign Key. In this case, set "user_id_similar" to be the FK, and include should then use that when performing the join.