0

I have the following database:

class User < ActiveRecord::Base
  has_and_belongs_to_many :apps

class App < ActiveRecord::Base
  has_and_belongs_to_many :users

In the view for a User (users/show.html.haml) I want to list all the Apps sorted by the ones the current user has.

%table
  %thead
    %tr
      %th Name
      %th Available
  -  for app in App.order("??????")
    %tr
      %td= link_to app.name, app_path(app)
      %td 
        - if @user.apps.include?(app)
          %i.icon-ok
        - else
          %i.icon-remove

My question is what do I put in the order function to do the sort.

James Brooks
  • 4,135
  • 4
  • 26
  • 25

4 Answers4

2

or via something like this:

App.all.partition{|app| @user.apps.include?(app)}.flatten

There is more than one way to do it!

jdoe
  • 15,665
  • 2
  • 46
  • 48
1

If I understand right, you want to sort the apps with the ones belonging to the current user coming first. I don't think this is possible in one query. I think the simplest way would be to split it into two queries:

user_apps     = current_user.apps
non_user_apps = App.where(:id.not_in => current_user.app_ids)
@apps         = user_apps + non_user_apps

Then you can just iterate over this @apps array, and the elements will be in the order you want.

tsherif
  • 11,502
  • 4
  • 29
  • 27
  • 1
    No worries. Just keep in mind that that solution will be a little bit slower because the `include?` part takes it from `O(n)` to `O(n^2)`. You shouldn't notice unless your list gets fairly long, though. – tsherif Apr 10 '12 at 15:49
  • Good point. Am I right in saying that yours is `O(n)` but that it traverses the db twice; that is a lot better if the table gets big. It shouldn't matter as I'm expecting of the order of 100 records in App. – James Brooks Apr 10 '12 at 16:52
  • Actually, there are three database hits. `current_user.group_ids` does one too, because it has to access the join table. That's one caveat with Ruby and Rails: that they sometimes hide a lot of complexity behind seemingly simple method calls. Generally, I like to have the database prepare the data as much as possible before I use it. It will generally be more efficient than preparing it in code. E.g. doing `App.order(:name)` is much faster than `App.all.sort_by(&:name)`. Anyway, it all depends on your needs. Happy coding! – tsherif Apr 10 '12 at 17:05
0

In the order method you can put any App's method name you want. It can be

App.order(:id)
App.order(:name)
App.order(:created_at)

or anything else.

denis.peplin
  • 9,585
  • 3
  • 48
  • 55
  • I realise that, I even have it in my example code. How do I say I want `App.order(@user.apps.include?(this))` or something to that effect – James Brooks Apr 10 '12 at 15:32
0

Try this: @user.apps.order(:name)

Ben Miller
  • 1,464
  • 12
  • 13
  • That will not include the apps that he does not own, only the one has has a link to. I need to show **all** the Apps. – James Brooks Apr 10 '12 at 15:30