In Active Record, how to find nil nested models - ruby-on-rails

I have many photos that belong to Movie like Movie.photos. Some movies have photos some other not.
How can easily find all the movies with no photos?

Put this method in your Movie model
def self.no_photos
Movie.all.reject{|movie| movie.photos}
end
You can use it this way.
movies_with_no_photos = Movie.no_photos

Related

Get all parent associations for children

I am doing the below to get all photos that are tagged with the same tag. What I also want to get is a list of the Albums in which those photos appear.
#photos = Photo.tagged_with(#tag)
I've tried doing the following but it fails.
#albums = #photos.albums
Any ideas?
#photos is not a singular object, it will return an array of ActiveRecord objects, so you can't do #photos.albums. Assuming there's a one-to-many relationship between the two models, then you have to get each photo then get the albums associated with it.

Rails, after a record is created, how to automatically create an associated record?

I have a Ratings model where a user can rate an object... After a rating takes place I want to then automatically create a RatingLog record so the user can see a list of all the ratings.
Models: Rating.rb and RatingLog.rb
I see RatingLog including a list of events other than just Ratings, like Badges etc... VERY similar to StackOverflow.
What is the right way with Rails 5, to populate RatingLog.rb after a Rating is created... Should I use after_create in Rating.rb? Should I create some other type of callback? Would love to hear what is the right way to implement the above in Rails 5.
Thank you
I assume that you have models:
class Rating
has_one :rating_blogs
end
class RatingBlog
belongs_to :rating
end
so, to create a rating blog afer rating is created, you can do:
#rating = Rating.new
#rating.build_rating_blog(some_message: 'Message')
#rating.save
So when #rating is created, a rating blog will be created and associated with #rating.
I don't know if this is considered okay... But I do this right inside of the create action, in your case I'll guess:
RatingController
def create
...
#ratinglog = RatingLog.create
#ratinglog.user = current_user
#ratinglog.rating = #rating.id
#ratinglog.comment_type = "server generated"
#ratinglog.comment = "#{current_user.fname} #{current_user.lname} submitted a rating of #{#rating.content}"
#ratinglog.save!
...
end
Another option is an after_commit callback which will only run when the Rating object is saved.
after_create will work too, but if you have an error when you try to save your RatingLog then the Rating record you created will also not save (checkout this answer).
So depending on the behavior you want, choose one:
after_commit RatingLog errors don't effect Rating saves
after_create RatingLog errors rollback Rating saves
Also:
It's not totally clear from your post, but it sounds like Rating and RatingLog are holding very similar data?? or if RatingLog will hold logs of other events, maybe name it something else.
Check out this answer on naming conventions -- the convention for model file naming is rating.rb and rating_log.rb

Rails querying database [duplicate]

This question already has answers here:
Rails where condition using NOT NIL
(5 answers)
Closed 8 years ago.
I am trying to create an instance Object of all Users that have one or more Video in my controller, so there is one User that has many videos. So I have a User.rb model that has_many :videos, and my Video.rb model that belongs_to :user. I want to select all the users that have atleast one video.
I am really new at querying SQL so I'm not sure how to join tables or if I even need to.
ex:
#users = User.where(user.video not nil?)
I want to select all the users that have atleast one video.
All you need to do is use joins method
#users = User.joins(:videos)
It will retrieve all users which have associated video(s) i.e., users without any associated videos would not be part of the results and query formed would be:
SELECT users.* FROM users
INNER JOIN videos ON videos.user_id = users.id
As #engineersmnky pointed out in this comment, if you are planning to iterate over the users retrieved in #users and then again go through the videos of each user then it would be a better idea to go for eager loading rather than joins to avoid the n+1 queries problem. In that case your code should be:
#users = User.includes(:videos).where("videos.id IS NOT NULL")
and for Rails 4 and above
#users = User.includes(:videos).where.not(videos: {id: nil})
Something like this
User.includes(:videos).where("videos.user_id is not null")

Ruby on Rails - How to Query on model/condition on controller?

I'm using rails 3.2.3 and have a questions about queries.
I've read that it is favorable using arel instead of named scopes.
Basically in my app, when a user logs in, I want him to see the products that he created.
So instead of having in my controllers index:
products=Product.find(:all)
I was looking for something like
products=Product.find(:all, :conditions....)
The thing is, my User and Product models have a HABTM relation (it really has to be) and I don't know how to join those tables so that only the products inserted by the current_user are displayed (the insertion is working correctly)
Do I have to add a search method in my Product model?
Or this can be accomplished by passing :conditions in the index controller?
Basically the logic is:
->Get all the products
->inner joining with the products_users HABTM table and get all the products where products_users.user_id = current_user.id. Return the results.
I don't know if I'm missing something here...any tips on how to code this? I'm kind of confused.
if user_sighed_in?
#products = current_user.products
else
#products = Product.scoped
end
ofc u have to define association in User model
has_many :products
If you have associated User and Products models - this code #products = current_user.products will return products of current_user.
To find all the products of current user this will do the trick
current_user.products

Calling a method on an attribute in rails

I am working on a tutorial and I wanted to really learn by deviating from the tutorial a bit and am encountering some problems. I am creating a showtime app that lists all the movies, times, genres, etc.
I have a Movie model with the attributes name, genre, showtime, showdate, release year, and title. In my movie.rb file, I added an attr_accessor :genre so I can use the setter and getter methods, but when I go into rails console and create a movie with all the attributes, the :genre keeps coming up as "nil" but when I call the movie.genre, it comes up as the correct listed genre. I am not sure why that is?
Also, since genre is not a class, are there any methods I can call on it to list all the genres in the database?
Thank you!
Is genre a column in your movies table? If so, why use attr_accessor?
For the second part of your question, you could write a class method in movie.rb to list all genres. Something like:
def self.genres
Movie.all.map(&:genre).uniq
end

Resources