I have a problem displaying files accessible via my application. When a user logs in, I want to display all of their files. Files downloaded by current user should be displayed last. The file table has about 500 records, so I need simple and fast method to achieve this.
class User
has_many :downloads
has_many :downloaded_files, :through => :downloads, source: :file
end
class File
attr_accessor :downloaded
has_many :downloads
has_many :users, :through => :downloads
end
class Download
belongs_to :user
belongs_to :file
end
The technologies I am using
Honestly, I see no need to over-think this issue. Five hundred records is nothing in terms of DB load, so just fire off two queries:
Your controller's code
# Current user files
@user_files = current_user.downloaded_files
# Select all files which don't have Download record for current user
@other_files = File.where("NOT EXISTS (SELECT 1 FROM downloads WHERE file_id = files.id AND user_id = ?)", current_user.id)
Then just use @user_files and @other_files in your view one after another. Something like
Your view's code
<%= render partial: 'files', collection: @other_files %>
<%= render partial: 'files', collection: @user_files %>
UPD
Using Where Exists gem (disclosure: I've released it recently) you can simplify your controller code.
Instead of this:
@other_files = File.where("NOT EXISTS (SELECT 1 FROM downloads WHERE file_id = files.id AND user_id = ?)", current_user.id)
You can write this:
@other_files = File.where_not_exists(:downloads, user_id: current_user.id)