follow and following with status - ruby-on-rails

i'm working on follow and following functionality with help of this article https://www.railstutorial.org/book/following_users
It's working fine but i added extra column with name status as a boolean which present the follow request has been accepted. current_user.following return all relations of current_user but i need those users whose relationship status is true.
My code is totally same as mention article , only i added status column in relationship table.
So kindly help me

I don't know the original code, but intuitively this should work
current_user.following.where(status: true)

As https://www.railstutorial.org/book/following_users:
class User < ApplicationRecord
has_many :microposts, dependent: :destroy
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
.
.
.
end
So, I think you can do like below to solve your problem:
class User < ApplicationRecord
has_many :microposts, dependent: :destroy
has_many :active_relationships, ->{ where(status: true) },
class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
.
.
.
end
Hope it helps.

Related

Rails has_many :through, how to list all objects to which an object belongs?

A character has_many :conversations, through: :chats.
However, each conversation belongs to two or more characters: Each conversation_id in the chats table is repeated at least twice, each with a different character_id, pointing to multiple characters of the same conversation.
character.rb
has_many :chats, foreign_key: "character_id", dependent: :destroy
has_many :conversations, through: :chats, source: :conversation
chat.rb
belongs_to :character
belongs_to :conversation
conversation.rb
has_many :messages
Is there a nice quick railsy way to list all the characters that a conversation belongs to? You'd think something like #conversation.characters would do the trick, but rails doesn't recognise this.
You have to set up the relationship from your Conversation model as well.
has_many :chats, dependent: :destroy
has_many :characters, through: :chats
Then you can easily call #conversation.characters
Quick tip
By the way, your Character model can be simplified, no need to define the standard foreign_key and source.
has_many :chats, dependent: :destroy
has_many :conversations, through: :chats

has_many :through association in the Rails tutorial

I don't get something in the last chapter of the Rails tutorial.
So the aim of this chapter to make friendships with other users, and that makes it a self referential association. (users have a relationship with other users)
So with the User model, there is the Friendship model, that acts as a through table.
And in the code, class User
class User < ActiveRecord::Base
has_many :microposts, dependent: :destroy
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
.
.
.
end
But I don't get this part:
has_many :following, through: :active_relationships, source: :followed
has_many :followers, through: :passive_relationships, source: :follower
We have to specify in the has_many :through association the table that we are going through (Relationship table). But in the above code there isn't an
:active_relationships or :passive_relationships table ,there's only a Relationship class.
The Relationship table:
class Relationship < ActiveRecord::Base
belongs_to :follower, class_name: "User"
belongs_to :followed, class_name: "User"
validates :follower_id, presence: true
validates :followed_id, presence: true
end
So, my question is, how does that work?
Tnx Tom
You are right you have just Relationship class.
In rails by default there will be has_namy :relationships then you don't have to specify the class name.
If you don't follow the rails default rules, then when you will try to with different association name , you have to specify the class name.
In your example
has_many :active_relationships, class_name: "Relationship",
foreign_key: "follower_id",
dependent: :destroy
Here you specified to find active relationships from Relationship class.
The has_many :through refers to an association.
has_many :following, through: :active_relationships, source: :followed
The has_many :through refers to an association, not a table. The :source is a relationship in the class that that association refers to.
In this case
has_many :followers, through: :passive_relationships, source: :follower
refers to this relationship
has_many :passive_relationships, class_name: "Relationship",
foreign_key: "followed_id",
dependent: :destroy
And in the relationship class, there is a :follower that is the actual source for this object.

Undefined method on custom has_many with source

Run.rb:
has_many :schedule_machines, through: :schedule_locations
Schedule.rb:
has_many :schedule_locations, dependent: :destroy
has_many :schedule_machines, through: :schedule_locations
has_many :assigned_schedule_machines, through: :runs, source: :schedule_machines
has_many :runs, dependent: :destroy
when I look at a Schedule in the console,
schedule.assigned_schedule_machines
gives an undefined method.
How come?
has_many :runs, dependent: :destroy
has_many :assigned_schedule_machines, through: :runs, source: :schedule_machines
You need to order the "runs" first. The assigned_schedule wants to use runs; but in your original code the runs wasn't defined yet.

has_many through can not modify association

I have three models: Almon, Bela and Lingo
class Almon < ActiveRecord::Base
belongs_to :bela, dependent: :destroy
has_many :lingos, through: :bela, dependent: :delete_all
accepts_nested_attributes_for :bela
accepts_nested_attributes_for :lingos, :allow_destroy => true
end
I am trying to submit a nested form in Almon and I am getting
Cannot modify association 'Almon#Lingos' because the source reflection class 'Lingo' is associated to 'Bela' via :has_many.
Could anyone please tell me what I am doing wrong?
You need to use has_many instead of belongs_to as the following:
has_many :belaes, dependent: :destroy
has_many :lingoes, through: :belaes, dependent: :delete_all

Rails has_many :through --> How do you set up an association to pull from multiple join models?

I'd like to set up multiple has_many :through relationships in parallel. Here are my 2 standard and 2 join models:
User.rb
has_many :ownerships, dependent: :destroy
has_many :devices, through: :ownerships
has_many :bookings, dependent: :destroy
has_many :devices, through: :bookings
Ownership.rb
belongs_to :user, touch: true, counter_cache: :devices_count
belongs_to :device, touch: true
Booking.rb
belongs_to :user, touch: true, counter_cache: :bookings_count
belongs_to :device, touch: true, counter_cache: :bookings_count
Device.rb
has_many :ownerships, dependent: :destroy
has_many :users, through: :ownerships
has_many :bookings, dependent: :destroy
has_many :users, through: :bookings
This current setup is NOT working as expected, there seems to be crosstalk between the join models. I want the join models to be independent and in parallel (i.e. Users can have relationships - Ownerships - with devices independently of being able to book them). I am not looking for a nested has_many :through relation here.
When I change the User Ownerships of a Device that seems to alter the number of Bookings and vice versa... any ideas on how should I be setting this up correctly?
I think the first error you've got is you're calling two associations by the same name (users / devices)
To help any further respondents, the real question is --> how do you set up an association to pull from multiple join models?
Quick Fix
Rails associations are named primarily by their class, but because of conflicts, you should refrain from setting them twice. This is why you're seeing the current issue. A simple resolution will be to call the associations by different names:
User.rb
has_many :ownerships, dependent: :destroy
has_many :owner_devices, through: :ownerships, class_name: "Device", foreign_key: "ownership_id"
has_many :bookings, dependent: :destroy
has_many :booking_devices, through: :ownerships, class_name: "Device", foreign_key: "booking_id"
I am still looking for information on how you could set an association to use two models
This appears be a working solution following Rich Peck's suggestions:
User.rb
has_many :ownerships, dependent: :destroy
has_many :device_ownerships, through: :ownerships, class_name: "Device", foreign_key: "device_id", source: :device
has_many :bookings, dependent: :destroy
has_many :device_bookings, through: :bookings, class_name: "Device", foreign_key: "device_id", source: :device
Booking.rb (Join model)
belongs_to :user, touch: true, counter_cache: :bookings_count
belongs_to :device, touch: true, counter_cache: :bookings_count
Ownership.rb (Join model)
belongs_to :user, touch: true, counter_cache: :devices_count
belongs_to :device, touch: true, counter_cache: :users_count
Device.rb
has_many :ownerships, dependent: :destroy
has_many :user_ownerships, through: :ownerships, class_name: "User", foreign_key: "user_id", source: :user
has_many :bookings, dependent: :destroy
has_many :user_bookings, through: :bookings, class_name: "User", foreign_key: "user_id", source: :user
To be honest, I'm a bit confused over why the foreign_key's need(?) to be set up as they are, so I'll have to do a bit more reading about it. Otherwise it appears to be functional, I don't see crosstalk between these join models anymore.

Resources