I'm learning Rails and I'm trying to connect the dots between Ruby and what's going on when creating associations. For example:
class Post < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_many :posts
end
I've read an explanation online that relates the use of belongs_to and has_many here to attr_accessor in Ruby. This is a tad confusing ... how is that so? I understand this sets up the 1:M association between Post and User, specifically Post has a foreign key containing a user id. In the rails console, I can do something like:
user = User.first
user.posts
user2 = User.create(username: 'some guy').save
post2 = Post.new(title: 'stuff', body: 'some more stuff')
user2.posts << post2
So are these kind of like 'getter' and 'setter' methods where an object of each class corresponds to a specific row in the database and I can use these methods because of their association/relationship?
To answer your exact question, the answer is "kinda yes, kinda no".
What rails does internally to set up the association is pretty complicated. yes, getter/setter methods are involved, yes, pointing at table rows are involved... but this isn't exactly what Active Record does, and it isn't only what Active Record does.
If you really want to know what Active Record does inside: you can just go and look at the source code on github.
If you have a more specific question... I recommend you update your question to ask that :)
Related
I've not been able to figure this one out -- perhaps I've missed something in the docs. I want to get all of the articles that are associated with published issues. (That is, article.issue.is_published = true.)
I have two models:
# Article model
class Article < ActiveRecord::Base
belongs_to :issue
...
end
# Issue model
class Issue < ActiveRecord::Base
has_many :articles
...
end
From what I understand, I can run something like this:
Article.includes(:issues)
.where('issue.is_published = true')
.references(:issues)
But I get nothing but funky business on the other end. All of the examples I've found have one-to-many relationships going the other way - I assumed that I've gotten something wrong with the naming convention, but no combination of "issue" and "issues" seems to work any better.
What am I missing here?
You'll want to do a joins instead of includes here. This translates to a SQL inner join. Article.joins(:issue).where(issues: {is_published: true})
I'm not getting a concept (nothing new there) on how to scope a Active Record query. I want to only receive the records where there is a certain condition in a related record. The example I have happens to be polymorphic just in case that is a factor. I'm sure there is somewhere where this is explained but I have not found it for whatever reason.
My Models:
class User < ActiveRecord::Base
belongs_to :owner, polymorphic: true
end
class Member < ActiveRecord::Base
has_one :user, as: :owner
end
I want to basically run a where on the Member class for related records that have a certain owner_id/owner_type.
Lets say we have 5 Members with ids 1-5 and we have one user with the owner_id set to 3 and the owner_type set to 'Member'. I want to only receive back the one Member object with id 3. I'm trying to run this in Pundit and thus why I'm not just going at it form the User side.
Thanks for any help as always!!!
Based on your comment that you said was close I'd say you should be able to do:
Member.joins(:user).where('users.id = ?', current_user.id)
However based on how I'm reading your question I would say you want to do:
Member.joins(:user).where('users.owner_id = ?', current_user.id)
Assuming current_user.id is 3.
There may be a cleaner way to do this, but that's the syntax I usually use. If these aren't right, try being a little more clear in your question and we can go from there! :)
I am using Ruby on Rails 4.1 and I would like to know if it is good and what are the drawbacks of creating a associated record just after the associator record creation. That is, for example, I have the Article class and the Comment class that belongs_to Article and I would like to create a "default" comment just after an article is created.
Probably I can use a callback method to accomplish that, but are there other approaches to accomplish what I looking for? What should I look at to be "balanced" (eg: class/module dependencies)?
You are looking for something along the lines of...
Class Article
has_many :comments
after_create :create_first_comment!
def create_first_comment!
comments.create
end
end
I have a Record model and in order to edit this model, you must be logged in as an instance of Admin. I would like to have a column called last_modified_by which points to the Admin who last modified the Record. In the database, I was thinking it would be good in the records table to add a column that holds the Admin's id; however, the only way I know how to do that is with an association. These two models are not associated with each other so an association doesn't make a lot of sense. Is there any other way I might be able to accomplish this task without resorting to associations? Any advice would be much appreciated!
Hmm, I think the association is a good tool here. You might want to try to hack it somehow but I think nothing you can conjure up will ever be as good as an association via a foreign_key(also so fast). But perhaps you would like to name your association and do something like:
class Record < ActiveRecord::Base
belongs_to :culprit, :class_name => 'Admin', :foreign_key => 'last_modified_by'
end
or give it some more senseful naming?
You could create an Active Record before_save callback. The callback would save the admin's id into the last_modified_column. This would make sure the admin id is saved/updated each time there is a change to the model.
For example, assuming admin is #admin:
class Record < ActiveRecord::Base
before_save :save_last_modified
def save_last_modified
self.last_modified_column = #admin.id
end
As for getting #admin, you could employ a method similar to this, and set #admin = Admin.current (like User.current in the link) somewhere in the Record model.
Im trying to display recently added comments from tattoos a user has posted. So If I posted a tattoo, and then user_b posted "hey I like your tattoo" then Im trying to get just the comment.
First of all Im using the acts_as_commentable_with_threading gem which doesnt create a foreign key for the table im trying to join. So my controller cant look for tattoo_id, it has to look for commentable_id
In the controller I would have to call the Comment model and then pass some SQL stuff into it but apparently I have no clue how to pass custom SQL queries into ruby because even tho my query string works in terminal, I get all sorts of nonsense when trying to use it in rails.
Im basically trying to do this:
SELECT comments.id FROM comments,tattoos WHERE commentable_id = tattoos.id AND
tattoos.member_id = #{current_user}
where #{current_user} will be the current_user passed in.
You don't have to jump through so many hoops to accomplish this. acts_as_commentable assigns a polymorphic association, so you should set it up like this:
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :commentable, :polymorphic => true
end
class Tattoo < ActiveRecord::Base
has_many :comments, :as => :commentable
end
class User
has_many comments
end
Then you can access the association as usual:
Tattoo.where(:member_id => current_user).first.comments
See http://railscasts.com/episodes/154-polymorphic-association for a general tutorial on how polymorphic associations work. It just so happens that this railscast uses exactly :commentable as the polymorphic example, so you should be able to follow along directly if you want.
I think Ben's approach is best but for future reference if you do come across something more complicated you can always use sql for example:
Comment.find_by_sql("SELECT comments.* FROM comments,tattoos WHERE commentable_id = tattoos.id AND tattoos.member_id = ?", current_user)