Rails 3 - Setting up PhotoAlbum & Photos - ruby-on-rails

I've created:
PhotoAlbum (id, name)
has_many: photos
Photo (id, name, photo_album_id)
belongs_to: photo_album
I want to allow a user to upload 1 or more photos. Per Upload whether it be 1 or more photos, they should automatically be added to a new album.
So the way i have it is, a user clicks upload photos:
They get the photo view where they get the form. They can then upload 1 photo (in the future I want to support more than 1, but baby steps!
so now in my Photos Controller, I have DEF CREATE
Q: How in the DEF CREATE, do I auto create an album and then create the photos? Something like?
#photo_album = PhotoAlbum.create
#photo = #photo_album.create(params[:photo])
? Is this the right Rails way to do this?
Thanks

#photo_album = PhotoAlbum.create({:name => "My Photo Album"})
#photo = #photo_album.photos.build({:name => params[:photo]})
I'm assuming your params[:photo] is the name, but you get the idea.

Related

Add an element to a Rails will_paginate collection

I have a Location model that has_many LocationPhotos. The Location also belongs_to a single LocationPhoto as the featured_location_photo. The belongs_to association looks like this:
class Location < ActiveRecord::Base
belongs_to :featured_location_photo, class_name: 'LocationPhoto', foreign_key: 'featured_location_photo_id'
end
Using will_paginate, I can paginate the photos for a location like this:
location.location_photos.paginate(page: 1, per_page: 4)
Ideally, I would like to always include the featured_location_photo as the first element, on the first page, of the collection that's returned, and not be included again. So, for example, if the related photos have ids 1,2,3,4,5,6 and the featured photo has id 3, I would want page one to show photos with ids:
3, 1, 2, 4
And page two to show photos with ids:
5, 6
The collection should also show total_entries equal to 6.
Is there any way to do this? I can't think of a way to do it by scoping the query because there's no way to tell the featured photo to sort to the top of the results.
My other thought is to first check if the location has a featured photo. If it does, remove that from the query with a scope:
result = location.location_photos.where.not(id: [featured_photo_id]).paginate(page: 1, per_page: 4)
Then, I would need to add the featured photo back into the front of result.
I'm totally saving this, because I've needed to solve this problem before and always copped out on the solution. Thanks for making me find this!!!
To promote a specific record in a collection use:
order("case when id = #{id} then 0 else id end")
Which means you can just create a custom scope like so:
class Location < ActiveRecord::Base
def photos
location_photos.
order("case when id = #{featured_location_photo_id} then 0 else id end")
end
end
EDIT: actually, ActiveRecord relations respond to unshift just like arrays. So all you actually need is this:
def photos
location_photos.unshift( featured_location_photo )
end
Which of course you can then paginate.
I think that you could improve your models by removing the dual association and adding a column on the location photo model named featured.
This way you can have more than one featured photo for each location (eventually in the future this may be needed).
After that you can use:
location.location_photos.order(:featured).paginate(page: 1, per_page: 4)
And that would do the trick.
NOTE: I am aware that adding a column would cause most of the images to have an empty field on the table, but space is not a problem nowadays.

Making a scope for Users with no role (rolify)

Im having trouble to show the photos from a my Usermodel.
I want to show the photos ONLY from the users that don't have role assigned with rolify.
So, I need to create a query for it:
#photos = Photo.where(User.find_by(Role == nil))
I can't get the scope to work...
Can someone give it a try?
Thanks!
To get all users with no role:
User.with_role(nil)
So, assuming that Photo belongs_to :user (photos table should have a user_id column):
#photos = Photo.where(user_id: User.with_role(nil))

How to Associate 5 atmost pictures with a account

I have a model Company which has_many :company_pictures but at most 5 photos. I have to show user all 5 file field for image uploading.
class Company < ActiveRecord::Base
has_many :company_pictures
accepts_nested_attributes_for :company_pictures
end
class CompanyPicture < ActiveRecord::Base
belongs_to :company
has_attached_file :picture, :styles => { :medium => "300x300>"}
end
controller code
def new
#company = Company.new
5.times { #company.company_pictures.build }
end
Now through this in new form I am able to show 5 file field. Now on submit . let say now my form did not get saved because of any other error. now I find only those file field that hold some value with that. i want to make sure that user will always able to attach at most 5 photos whether he is creating a new company or updating a company.
What I usually do in this cases is that before presenting the user with the "new" layout, I create and save the object first in the database with a "draft" status with the objective of getting a primary key and be able to save the pictures (the pictures need a primary key in order to be saved). Then, when the user submits the form, no matter if there are errors or not I always save the pictures and then present the user with the form, the errors (in case there are) and since the images got saved to the database you can display them to the user. If there are no errors just remove the "draft" status from the user and continue your workflow.
Now the question is, what do we do with all those drafts ? Create a rake task that run's every hour and delete all the records in this state.

In Active Record, how to find nil nested models

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

rails find model without loading relevant associations

My rails application has two models, gallery and photo. Galleries have many photos and photos belong to one gallery.
When I delete a photo, I noticed that rails also loads the gallery - which I do not need. It is an added database query.
When I find the photo to delete, I use #photo = Photo.find(params[:id]). This loads the association.
I know that there is #photo = Photo.find(params[:id], :include => :gallery), which tells it to load the gallery. What is the opposite of this? I tried the following:
#photo = Photo.find(params[:id], :include => [])
#photo = Photo.find(params[:id], :include => nil)
I also tried to select only the fields that I need in order to delete the photo, but I need the gallery_id in order to delete the actual file because the path of the file is based off the gallery. This just ends up loading the gallery too.
Edit:
My Photo model looks like this:
class Photo < ActiveRecord::Base
belongs_to :gallery
mount_uploader :file, PhotoUploader
end
mount_uploader is from carrierwave. I have an uploader with the following code in it:
def store_dir_base
"galleries/#{model.gallery.id}/"
end
Could it be the culprit?
Thanks!
The reason this was happening was because of my uploader code that I used for carrierwave.
This code was accessing the gallery model, when all I needed to access was the id:
def store_dir_base
"galleries/#{model.gallery.id}/"
end
All I had to do was change it to:
def store_dir_base
"galleries/#{model.gallery_id}/"
end
This made it so I was accessing the photo model column gallery_id instead of the gallery model.

Resources