0

I use Rails 4. I have an application where i have a many-to-many relationship :

class User < ActiveRecord::Base
  has_many :relationshipfollows, :foreign_key => "follower_id",
                           :dependent => :destroy
  has_many :following, :through => :relationshipfollows, :source => :followed
end

class Project < ActiveRecord::Base
 has_many :relationshipfollows, :foreign_key => "followed_id",
                           :dependent => :destroy
 has_many :followers, :through => :relationshipfollows, :source => :follower
end

class Relationshipfollow < ActiveRecord::Base
  belongs_to :follower, :class_name => "User"
  belongs_to :followed, :class_name => "Project"
end

I follow this tutorial : http://ruby.railstutorial.org/chapters/following-users?version=3.0#top

But now I'd like to list all projects ordered by the number of follower. Like this :

1. project1 | 99 followers
2. project2 | 16 followers
3. project3 | 2 followers
...

I'm new to rails and I guess I keep making a mistake because I try a lot of examples like this : Rails 3 Order By Count on has_many :through or has_many , through: relationship count

I try this method : Project.joins(:relationshipfollows).group("relationshipfollows.project_id").order("count(relationshipfollows.project_id) desc")

But i have this error : SQLite3::SQLException: no such column: relationshipfollows.project_id: SELECT "projects".* FROM "projects" INNER JOIN "relationshipfollows" ON "relationshipfollows"."followed_id" = "projects"."id" GROUP BY relationshipfollows.project_id ORDER BY count(relationshipfollows.project_id) desc

And I try a another method :

Project.joins(:relationshipfollow).select('following.*, COUNT(followers.id) AS user_count').group('project_id').order('COUNT(followers.id) DESC')

But I have this error : Association named 'relationshipfollow' was not found on Project; perhaps you misspelled it?

Could someone please help me to find the right direction how to make it all work ?

Cordially

Edit : I think the problem its from here. When I try this :

Relationshipfollow.select(:followed_id, "COUNT(follower_id) AS total").group(:followed_id).order("total DESC")

he return me this :

=> # ActiveRecord::Relation [# Relationshipfollow id: nil, followed_id: 2, # Relationshipfollow id: nil, followed_id: 1, # Relationshipfollow id: nil, followed_id: 3]

All projects are ordered by the number of followers and all followed_id (projects) are in the good order in relative of my test. But when I join this to my model Project like this :

Project.joins(:relationshipfollows).select(:followed_id, "COUNT(follower_id) AS total").group(:followed_id).order("total DESC")

he return me a list of projects but with project_id NULL :

=> #ActiveRecord::Relation [# Project id: nil, # Project id: nil, # Project id: nil]
Community
  • 1
  • 1
Bibou
  • 133
  • 1
  • 9
  • what you actually want to do with the queries and what is the outcome of activeRecord methods ?? – Saghir A. Khatri Mar 28 '14 at 03:53
  • I have edit my post for more clarity. I would like to find a queries for return a list of project ordered by the number of follower. I tried 2 different methods (queries) but no one work. Maybe because I making a mistake. – Bibou Mar 28 '14 at 04:36
  • try this `Project.joins(:relationshipfollows).select('following.*, COUNT(followers.id) AS user_count').group('project_id').order('COUNT(followers.id) DESC')` and let me know the result – Saghir A. Khatri Mar 28 '14 at 04:42
  • I have this error in my view when i do a .each on my variable : ActiveRecord::StatementInvalid `SQLite3::SQLException: no such table: following: SELECT following.*, COUNT(followers.id) AS user_count FROM "projects" INNER JOIN "relationshipfollows" ON "relationshipfollows"."followed_id" = "projects"."id" GROUP BY project_id ORDER BY COUNT(followers.id) DESC'` – Bibou Mar 28 '14 at 04:57
  • use this: it should solve your problem: `Project.joins(:relationshipfollows).select('followers.*, COUNT(followers.id) AS user_count').group('project_id').order('COUNT(followers.id) DESC')` – Saghir A. Khatri Mar 28 '14 at 05:00
  • Same error but this time with "no such table: followers" – Bibou Mar 28 '14 at 05:13
  • try this: `Project.joins(:relationshipfollows).select_all('followers.*, COUNT(followers.id) AS user_count').group('project_id').order('COUNT(followers.id) DESC')` – Saghir A. Khatri Mar 28 '14 at 05:25
  • otherwise i am now out of ideas :s – Saghir A. Khatri Mar 28 '14 at 05:25
  • Not the same error : `undefined method `select_all' for #` – Bibou Mar 28 '14 at 05:38
  • `Project.joins(:relationshipfollows).select('COUNT(relationship.*) AS user_count').group('project_id')' – Saghir A. Khatri Mar 28 '14 at 05:57
  • I have this error : ActiveRecord::StatementInvalid `SQLite3::SQLException: near "*": syntax error: SELECT COUNT(relationship.*) AS user_count FROM "projects" INNER JOIN "relationshipfollows" ON "relationshipfollows"."followed_id" = "projects"."id" GROUP BY project_id` I try on my side to find a solution but the problem its I don't understand what happen. I don't know if it's a queries problem or a another problem. Thank you Saghir A. Khatri for your help. – Bibou Mar 28 '14 at 06:11
  • try simplifying the stuff in your active record query and then start adding complex stuff like `group` and `count` – Saghir A. Khatri Mar 28 '14 at 06:13
  • Thank you for your help Saghir A. Khatri. I edited my post. Maybe my test will give you more informations about my mistake. – Bibou Mar 29 '14 at 06:37

3 Answers3

1

Here's what I would do:

#app/models/project.rb
Class Project < ActiveRecord::Base
     has_many :relationshipfollows, :foreign_key => "follower_id", :dependent => :destroy
     has_many :followers, :through => :relationshipfollows, :source => :follower

     scope :sort_by_followers, -> { joins(:followers).select("followers.*", "COUNT(followers.id) AS follower_count").group(:project_id).order("follower_count DESC") }
end

#app/controllers/projects_controller.rb
def index
    @projects = Project.sort_by_followers
end

#app/views/projects/index.html.erb
<ol>
    <% @projects.each_with_index do |project, i| %>
        <li><%= "Project#{i} | #{project.follower_count} followers" %></li>
    <% end %>
</ol>
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • Hello Rich Peck and thank you for your help. With your method I have this error : `ActiveRecord::StatementInvalid in Categories#show SQLite3::SQLException: no such table: followers: SELECT followers.*, COUNT(followers.id) AS follower_count FROM "projects" INNER JOIN "relationshipfollows" ON "relationshipfollows"."followed_id" = "projects"."id" INNER JOIN "users" ON "users"."id" = "relationshipfollows"."follower_id" GROUP BY project_id ORDER BY follower_count DESC` at this line : `<% @mostfollow.each_with_index do |project, i| %>` I really don't know what happen and where is my mistake. – Bibou Mar 29 '14 at 00:03
  • I edited my post. Maybe my test will give you more informations about my mistake. – Bibou Mar 29 '14 at 06:36
0

Project.joins(:relationshipfollows) will do an inner join. So, Projects without followers will NOT be included in the result set. You need something like this:

Project.select("projects.*, COUNT(relationshipfollows.follower_id) as follower_count").joins("LEFT OUTER JOIN relationshipfollows ON relationshipfollows.followed_id = projects.id").group("projects.id").order("follower_count DESC")
psparrow
  • 9,808
  • 1
  • 17
  • 11
-1

My rescues solution was to add a integer numberfollowers in my Project model

But with another project and the rails guides (http://guides.rubyonrails.org/active_record_querying.html), I finally found the answer to my request

Project.joins(:relationshipfollows).select('projects.*, COUNT(followed_id) as user_count').group('projects.id').order('user_count DESC')
Bibou
  • 133
  • 1
  • 9