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.
Related
I have a Rails database for reviewing things at a school. My tables are School, Major, Course, Instructor, Review. The way my team currently has the Review table set up, there are non-nullable foreign keys to each one of the other tables.
My issue with this is that to submit a new review the user would want to fill in only 1 of those foreign keys. Is there a way to do this with Rails? Even if there is, it seems like this would be a better use case for Instructor_Review, Course_Review, etc tables. That also has the (very nice) benefit of being able to customize table attributes for each review.
However, if we were to break up Review into multiple tables, is there a mechanism in Rails for having common columns? The overall_rating attribute would need to be included for every type of review, should the attributes just have the same name or is there a way for Rails to have table Subclasses (I know there is in SQL...)
I wouldn't create different models for the different review types if they are similar (apart from the thing the review is about). This is probably a source of duplication which should be avoided.
Instead, you could use a polymorphic association. Your review model has one thing the review belongs to (be it a school, a teacher, or an instructor). So lets model it like that. Give it a reference to that thing and the type of that thing (so that Rails knows which class it belongs to).
With polymorphic associations, your classes can be linked like this:
class Review < ActiveRecord::Base
belongs_to :reviewable, polymorphic: true
belongs_to :user
# ...
end
class School < ActiveRecord::Base
has_many :reviews, as: :reviewable
end
class Teacher < ActiveRecord::Base
has_many :reviews, as: :reviewable
end
On the database-level this means that your review table just needs one foreign key to point at the reviewable thing (plus one type column). The review-migration would look like this:
class CreateReviews < ActiveRecord::Migration
def change
create_table :reviews do |t|
t.references :user, index: true
t.references :reviewable, polymorphic: true, index: true, null: false
t.timestamps null: false
end
end
end
polymorphic: true lets Rails create the id- and type-column.
For details, please refer to the ActiveRecord documentation.
PS: There is also a RailsCast covering this issue. But beware: It's from 2009 - pretty old, but (from a quick glimpse at it) it should still work.
You are looking for polymophic relationships. Basically add a type column on the review and then you have to wire it up correctly. Here is a great article for that.
http://www.gotealeaf.com/blog/understanding-polymorphic-associations-in-rails
The review table will then have your common reviewable columns that will be shared. The next part is a little more complicated. You would then setup a review to have an extension.
To explain the extension, this is normally done when you have an entity that can either be a group or user (similar to how your InstructoreReview and CourseReview will by types of reviews). Those groups/users will have a profile that is similar to the extension of the review.
The ReviewExtension will have it's own table per review that you are extending and most of the time those extensions in their own review_extensions folder under models.
Once that is done you will delegate the common getter and setter methods you are wanting to the extension.
Hopefully this will at least give you enough to get going.
Suppose I have three models, set up something like this:
class Student < ActiveRecord::Base
has_many :tests
has_many :cars
end
class Car < ActiveRecord::Base
belongs_to :student
end
class Test < ActiveRecord::Base
belongs_to :student
end
I want to query all tests whose student does not have car. Preloaded.
I've tried the following:
Test.includes(:cars) # does not work because the two are not associated
Test.joins('inner join cars ON tests.student_id = cars.student_id') # works, but it doesn't preload the Cars model in my result
I'd prefer not to create a has_many :through relationship, because they really aren't related at all, but I'm not opposed to it if that's the best solution.
Thoughts?
Rails 4.1.5
PostgreSQL 9.3.4
ruby 2.1.2
A join across three tables is an inefficient way to do this. Rails might even be smart enough to realise this and split it into seperate db queries.
I would do it like this, which has two simple queries instead
student_ids_with_car = Car.select("student_id").distinct
#tests = Test.where("student_id not in (?)", student_ids_with_car)
You don't have to use has_many :through to associations and associations of those associations at the same time.
Test.includes(:student => :cars)
Will include student's and their cars (by default it will preload, you can force a joins based include by using eager_load instead of preload).
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
I have a basic problem with a has_one and belongs_to association. I have two models: StudentRegistration and User that look like the following:
class StudentRegistration < ActiveRecord::Base
belongs_to :user
end
and
class User < ActiveRecord::Base
has_one student_registration
end
The idea is that a student gets registered and then later a User account can be created. My problem is that I'm storing the foreign key user_id in the student_registration table and I only know this once the user record has been created. When the user account gets created I need to update the student_registration table adding the new user id.
Is it the case that I just have this the wrong way around or should Rails handle this automatically?
You have setup your associations the correct way, but I guess the implementation is wrong.
No problems, just go through this link and you'd be good to go.
Nested-model-form-part-1 - Railscasts
I'm having trouble finding a good tutorial on how to define basic foreign key relationships between models. suppose I have a User model and a Game model..
I would like to define two fields in the Game model - host_id and visitor_id which are mapped via foreign key relationship to the User model. The IDs of the 'host' and 'visitor' fields of the Game class basically define the two players which will engage in a peer-to-peer game... and those fields need to be mapped to actual users of the application as defined in the User model by userID..
Thank you!
Did try this http://guides.rubyonrails.org/association_basics.html?
I think it could be like this:
class User
belongs_to :game
end
class Game
has_one :host_user, :class_name => "User"
has_one :visit_user, :class_name => "User"
end