1

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

  • Rails 4.2.1
  • Ruby 2.2.2
  • PostgreSQL
wurde
  • 2,487
  • 2
  • 20
  • 39
Oskar
  • 43
  • 5
  • What do you mean by all of **their** files? When do you consider that file belongs to user? – EugZol Aug 04 '15 at 14:56
  • All upload files (few files don't have any users). Now i am using in files_controller.rb - `current_user.downloaded_files` for show only downloaded files by current user or `current_user.downloaded_files.include?(self)` for an single file. – Oskar Aug 04 '15 at 15:19
  • I've updated my answer with a more simple way to do such thing using my [Where Exists](https://github.com/EugZol/where_exists) gem. – EugZol Aug 30 '15 at 18:08

1 Answers1

0

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)
EugZol
  • 6,476
  • 22
  • 41