Order users based on when the relationship was created_at - sql

I used the Railstutorials to create followers and followed_users http://ruby.railstutorial.org/chapters/following-users#top
On the page where I want to show a specific persons' followers/followed_users, I'd like to show them based on when the relationship was created.
#users = #user.followers.order("created_at DESC")
Something like this ^^ just shows when the user was created, not when the relationship was created. How can I run this query efficiently to get the proper ordering?
def following
#users = #user.followed_users
end
def followers
#users = #user.followers
end
-User Model-
has_many :relationships, foreign_key: "follower_id", :dependent => :destroy
has_many :followed_users, through: :relationships, source: :followed
has_many :reverse_relationships, foreign_key: "followed_id",
class_name: "Relationship",
dependent: :destroy
has_many :followers, through: :reverse_relationships, source: :follower
- Relationship Model -
belongs_to :follower, class_name: "User", touch: true
belongs_to :followed, class_name: "User", touch: true
validates :follower_id, presence: true
validates :followed_id, presence: true

Since your user has there two relationships, you can easily access that table with the direction you want.
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :reverse_relationships, foreign_key: "followed_id"
First Answer (when they're a follower)
You have to use the relationships table because that record gets created when you get a new follower, thus you do this:
#user.relationships.order("created_at DESC").collect { |r| User.find(r.followed) }
Second Answer (when they're followed)
#user.reverse_relationships.order("created_at DESC").collect { |r| User.find(r.follower) }

Related

Rails simplify a query to get user profile's first_name

I want to retrieve application.applicant.profile.first_name for the applicant and I'm not able to retrieve the profile attribute:first_name using applicant above.
Profile, application are connected by foreign key: user_id to user.Can someone suggest a way?
Here are my associations:
user.rb
class User < ApplicationRecord
has_many :applications
has_one :profile, -> { where role: 'user' }, dependent: :destroy
profile.rb
class Profile < ApplicationRecord
belongs_to :user, :class_name => 'User', :foreign_key => 'user_id'
job.rb
class Job < ApplicationRecord
has_many :applications, :dependent => :destroy
has_many :applicants, :through => :applications, :class_name => 'User'
application.rb
class Application < ApplicationRecord
belongs_to :job
belongs_to :applicant, :class_name => 'User', :foreign_key => 'user_id'
This line isn't correct...
has_one :profile, -> { where role: 'user' }, class_name: 'User', dependent: :destroy
It should be...
has_one :profile, -> { where role: 'user' }, dependent: :destroy
The class_name for :profile is Profile but you don't need to specify it as it can be derived from the symbol by rails.
After numerous permutations and combinations such as polymorphic, select & join statement or even by providing a SQL query, finally realised that it was as simple as a single statement as I knew the user_id of current user:
<% post.applications.each do |papplication| %>
<%= Profile.find_by_user_id(papplication.user_id).first_name %> <% end %>

Order by count of association through join table

I have a show with many episodes, and episodes have many people through contributions. (see diagram below)
I added has_many :people, through: :contributions to Show so I can do: game_of_thrones.people.count, and even:
has_many :actors, -> { joins(:roles).merge(Role.actors).distinct },
through: :contributions, source: :person
-
game_of_thrones.actors.count
But what I would like to do is create a list of actors on game_of_thrones or breaking_bad, etc, ordered by the number of appearances on the show.
example:
Jon Snow: 9 episodes
Arya Stark: 8 episodes
Joffrey Lannister: 5 episodes
Tyrion Lannister: 2 episodes
My question is a two parter.
How do I return a list of top actors on a show ordered by their contribution count?
Should I be doing this through ActiveRecord or SQL queries. What would be a good reference to understand this better so I can stop bothering stack overflow?
class Show < ActiveRecord::Base
has_many :episodes, inverse_of: :show
has_many :contributions, through: :episodes
has_many :people, through: :contributions
has_many :actors, -> { joins(:roles).merge(Role.actors) },
through: :contributions, source: :person
end
class Episode < ActiveRecord::Base
belongs_to :show, inverse_of: :episodes
has_many :contributions, inverse_of: :episode
has_many :roles, through: :contributions
has_many :people, through: :contributions
end
class Contribution < ActiveRecord::Base
belongs_to :episode, inverse_of: :contributions
belongs_to :person, inverse_of: :contributions
belongs_to :role, inverse_of: :contributions
end
class Person < ActiveRecord::Base
has_many :contributions, inverse_of: :person
has_many :episodes, through: :contributions
has_many :roles, through: :contributions
scope :actors, -> { joins(:roles).merge(Role.actors) }
end
class Role < ActiveRecord::Base
has_many :contributions, inverse_of: :role
has_many :people, through: :contributions
has_many :episodes, through: :contributions
scope :actors, -> { where(name: 'Actor') }
end
failed queries: game_of_thrones.people.joins(:contributions).distinct.joins(:episodes).where("episodes.show_id = 1").order("count(episodes.show_id) desc")
game_of_thrones.guests.joins(:contributions).order("count(contribuions.id) desc")
This is how I solved it:
def top_contributors
self.people.select("people.id, count(contributions.id) AS contribution_count").
joins(:contributions).
joins(:episodes).
group("people.id").
order("contribution_count DESC").
limit(5)
end
Though I think this is counting all of a person's contributions regarless of shows.

Rails SQL query for mutual friends

My User model looks like this:
has_many :relationships, foreign_key: "follower_id", dependent: :destroy
has_many :followed_users, through: :relationships, source: :followed
has_many :reverse_relationships, foreign_key: "followed_id",
class_name: "Relationship",
dependent: :destroy
has_many :followers, through: :reverse_relationships, source: :follower
What I want is the raw SQL query to get users that a given user follows and is followed back by.
Currently I've only gotten as far as getting the ids of users I'm following:
followed_user_ids = "SELECT followed_id FROM relationships
WHERE follower_id = #{user.id}"
I have a rails methods that returns mutual friends, but I want the SQL equivalent:
def mutual_friends
# interesect both arrays to find similar elements
self.followed_users & self.followers
end
Something like this should work
SELECT followed_id
FROM relationships
WHERE follower_id = #{user.id} AND followed_id IN (
SELECT follower_id FROM relationships WHERE followed_id = #{user.id}
)
Please use it like this, let me know if it works for you.
has_many :company_friendships, autosave: true
has_many :company_friends, through: :company_friendships, autosave: true
has_many :inverse_company_friendships, class_name: "CompanyFriendship", foreign_key: "company_friend_id", autosave: true
has_many :inverse_company_friends, through: :inverse_company_friendships, source: :company, autosave: true
def mutual_company_friends
Company.where(id: (company_friends | inverse_company_friends).map(&:id))
end

Rails has_one with join table

In my app there are Athletes... athletes can have many sports.
Athlete:
has_many :sports, :through => :user_sports
has_one :primary_sport, conditions: ["user_sports.primary = ?", true], class_name: "Sport"
has_many :user_sports
UserSport:
class UserSport < ActiveRecord::Base
attr_accessible :athlete_id, :sport_id, :primary
belongs_to :athlete
belongs_to :sport
end
I am trying to be able to pull back the primary_sport as a Sport object instead of the user_sport object.
Since you pull your sports objects :through user_sports, you should pull your primary_sport object :through user_sports as well.
has_one :primary_sport, :through => :user_sports, conditions: ["user_sports.primary = ?", true], class_name: "Sport"

Rails 3 - WARNING: Can't mass-assign protected attributes: user_ids

I have a has_many through relationship between Course and User.
class Course < ActiveRecord::Base
belongs_to :user
has_many :enrollments, :dependent => :delete_all
has_many :users, :through => :enrollments
attr_accessible :description, :duration, :name, :prerequisites, :short_name, :start_date, :user_id
accepts_nested_attributes_for :users, :allow_destroy => true
attr_accessible :users_attributes
and User:
class User < ActiveRecord::Base
has_many :subjects, :class_name => "Course" # to get this call user.subjects
has_many :enrollments, :dependent => :delete_all
has_many :courses, :through => :enrollments
and Enrollment:
class Enrollment < ActiveRecord::Base
belongs_to :course
belongs_to :user
attr_accessible :course_id, :user_id
end
Now I'm trying to set user_ids from inside Course, using a nested form. It keeps giving me that Mass Assignment warning, and nothing is saved. I read I was supposed to add attr_accessible user_id but it still doesn't work.
Even if I do something like this from the rails console:
#c.update_attributes({:user_ids => [7,8]})
with #c being the course
Any help would be greatly appreciated,
Thank you.
It's user_ids, not user_id.
You need to add user_ids to your attr_accessible.