ruby-on-railsrubypostgresqlassociate

Rails: Order by associate, first not downloaded


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


Solution

  • 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)