Rails models association not working? - ruby-on-rails

thanks for this commmunity, it has helped me alot already. This is the first question I have to post myself, and it is somewhat specific to my project.
I have started from MHartls great rails tutorial.
There were models for Users and Microposts and I have added a Cars model, where each user can have a car (referenced by the car_id).
In the console I can create a user and a micropost, and assign the user to the micropost by stating post.user = michael and then it would set the post's user_id to michaels id.
I am trying to do the same for cars, where i can set a users car_id by stating michael.car = somecar but it gives an error even though the model associations LOOK exactly the same, and I have even remigrated the car_id to the user model as reference. See below:
class User < ActiveRecord::Base
has_many :microposts, dependent: :destroy
belongs_to :cars
class Micropost < ActiveRecord::Base
belongs_to :user
belongs_to :car
class Car < ActiveRecord::Base
has_many :microposts, dependent: :destroy
has_many :users
accepts_nested_attributes_for :users
accepts_nested_attributes_for :microposts
Here is my last migration for the car_id:
class Addreferencecartousers < ActiveRecord::Migration
def change
add_reference :users, :car
add_foreign_key :users, :cars
end
end
in synch with what I had done for the user/micropost connection.
I am kind of lost on where else to look for why this does not work, does anyone have any hints/pointers on what I am missing here?

To address your problem, the belongs_to :cars in the User model should be belongs_to :car, but in a reality I believe it will be more sense to call it as has_many :cars rather than a belongs_to :car because a user can have many cars and a car belongs to user

Related

How to get associated polymorphic objects in rails 5?

In my Post model, I have
has_many :followers
In my Follower model, I have
belongs_to :model
belongs_to :owner,polymorphic: true
In my User and Admin devise models, I have
has_many :followers,as: :owner
Requirement: I want to have something like Post.owners and it should return me a list of all users and/or admins that are following this post.
I'm not sure, but I think that AR doesn't provide a way to load polymorphic associations in just one query. But you can use:
post = Post.find(1)
post_followers = post.followers.includes(:owner)
post_owners = post_followers.map(&:owner)
The solution you're looking for is polymorphic has many through. You can add these lines in your model of User and Admin.
has_many :followers
has_many :posts, through: :followers, source: :owner, source_type: 'Owner'
I think you want something like this:
class Post < ApplicationRecord
belongs_to :owner, polymorphic: true
end
class User < ApplicationRecord
has_many :posts, as: :owner
end
class Follower < ApplicationRecord
has_many :posts, as: :owner
end
From an instance of your User you can then retrieve their posts with #user.posts
The same goes for your Follower, #follower.posts
If you want to get to the parent of your post instance, you can do so via #post.owner. To make this work, however, we need to set up the schema correctly by declaring both a foreign key column and a type column in the model that declares the polymorphic interface using the references form:
class CreatePosts < ActiveRecord::Migration[5.0]
def change
create_table :posts do |t|
# your attribs here
t.references :owner, polymorphic: true, index: true
end
end
end

How to reference a field in the join model of a has_many though Rails 5 relationship

I am working on an app where users have many quizzes and quizzes can have many users. I have set the relationships:
class User < ApplicationRecord
has_many :studies
has_many :quizzes, through: :studies
end
class Quiz < ApplicationRecord
has_many :studies
has_many :users, through: :studies
end
class Study < ApplicationRecord
belongs_to :user
belongs_to :quiz
end
I have a field in the Study table to store the score that the user made on the quiz, but I am unable to access the field. I have tried #quiz.studies.score and #quiz.study.score but Rails give me an undefined method. How to I access the field in a join model of a has_many though relationship?
#quiz.studies return the collection of studies. So you have to use first, last, each to get the score of the specific studies.
Try this:
#quiz.studies.first.score

Additional relation between records in Rails 5.0

I need your small advice help.
I have trivial models: Post and User.
A user has_many :posts and a post belongs_to :user. A post has one owner.
I need somehow add an additional relation: a post can have multiple contributors. A contributor is a user too. I need to be able to write something like this: #post.contributors (shows User records) and #user.contributed_to (shows Post records).
How do I do that?
You'll need many-to-many association here, because user has_many posts and posts has_many users.
To implement it, you need to create an additional model (for example, contribution with user_id and post_id columns)
class Contribution < ApplicationRecord
belongs_to :user
belongs_to :post
end
And your Post and User classes will contain something like this:
class Post
belongs_to :user
has_many :contributions
has_many :contributors, through: :contributions, source: :user
end
class User
has_many :posts
has_many :contributions
has_many :contributed_posts, through: :contributions, source: :post
end

Ruby on Rails: Many-to-Many Instance

New to rails. I'm creating a project with several database tables all in relation to each other. I would like to know how to add a foreign key reference to an instance after it has been created. Code below:
In schema:
class Blog < ActiveRecord::Base
has_many :posts
has_many :owners
has_many :users, through: :owners
end
class Owner < ActiveRecord::Base
belongs_to :user
belongs_to :blog
end
class User < ActiveRecord::Base
has_many :messages
has_many :posts
has_many :owners
has_many :blogs, through: :owners
end
Models:
class User < ActiveRecord::Base
has_many :messages
has_many :posts
has_many :owners
has_many :blogs, through: :owners
end
class Owner < ActiveRecord::Base
belongs_to :user
belongs_to :blog
end
class Blog < ActiveRecord::Base
has_many :posts
has_many :owners
has_many :users, through: :owners
end
In rails console:
blog1 = Blog.first
user1 = User.first
blog1.users = user1
NoMethodError: undefined method `each' for #<User:0x0000000487e9f8>
If you're trying to make it so that user1 becomes the owner of the blog, you could try
blog1 = Blog.first
user1 = User.first
Owner.create(user: user1, blog: blog1)
or
Owner.create(user: User.first, blog:Blog.first)
Hope I answered your question!
Since a Blog has many Users, .users will be a collection (Array or ActiveRecord_Relation).
Try: blog1.users << user1
<< (shovel operator) docs
When you are writing blog1.users, you are getting back an array, so doing = something wouldn't work. While you can just add to the array using << or say array.push(), it's not the best practice.
Instead, has_many (or has_one, etc), allows you to use build_ notation to create related objects. So you could do: blog1.users.build, which will create a new user referenced for the blog. Or if you want to persist it, you can call .users.create
There are many ways to go around it, but using ActiveRecord methods if available is a nice way to keep code readable and short.

multiple belongs_to models in Rails

I have a comments model that is currently working with Articles. I would now like to have users be able to comment on the Coffeeshop reviews. Am I able to use the same comment table, or should I have a separate one (feels janky). I've not long been building with RoR (a few weeks) so still trying to get the hang of the basics.
Would I nest them in routes.rb (and how)
resources :coffeeshops do
resources :articles do
resources :comments
end
or
resources :coffeeshops do
resources :comments
end
resources :articles do
resources :comments
end
My models look like:
User
class User < ApplicationRecord
has_many :comments
end
Comments
class Comment < ApplicationRecord
belongs_to :user
belongs_to :article
belongs_to :coffeeshop
end
Articles
class Article < ApplicationRecord
has_many :comments, dependent: :destroy
end
Coffeeshops
class Coffeeshop < ApplicationRecord
has_many :comments, dependent: :destroy
I'm then assuming I need a foreign key to tie the user and comments together, and then also the comments to the article/coffeeshop.
I'd use a polymorphic association.
http://guides.rubyonrails.org/association_basics.html#polymorphic-associations
class User < ApplicationRecord
has_many :comments
end
class Comment < ApplicationRecord
belongs_to :user
belongs_to :commentable, polymorphic: true
end
class Article < ApplicationRecord
has_many :comments, as: :commentable
end
class Coffeeshop < ApplicationRecord
has_many :comments, as: :commentable
end
For some more information about setting up the routes/controller:
https://rubyplus.com/articles/3901-Polymorphic-Association-in-Rails-5
http://karimbutt.github.io/blog/2015/01/03/step-by-step-guide-to-polymorphic-associations-in-rails/
You can use comment model for both comments for articles and coffeeshops, but (because by default rails uses ids as primary and foreign keys I assume you use ids too) you will have to add column to comments table, where you set the comment type (You can create Enumerator in comment model, where you set 2 possible value types, each for article and coffeeshop models). If you don't add the column it will result in weird, hard to track bug where you can see comments for article on coffeeshop with same id and vise-versa.
UPD: he's little guide on using enums for rails models: http://www.justinweiss.com/articles/creating-easy-readable-attributes-with-activerecord-enums/ you will have to use it not in actual add comment form, but behind the scenes.

Resources