I have an Address model that I need to abstract into Origin and Destination.
class Address
# ?
end
class Origin
has_many :destinations
has_many :addresses, through: :destinations
end
class Destination
has_many :origins
has_many :addresses, through: :origins
end
Related
I'll start off with my models:
class Project < ApplicationRecord
has_many :permissions
has_many :wallets, through: :permissions
has_many :follows
has_many :wallets, through: :follows
end
class Permission < ApplicationRecord
belongs_to :project
belongs_to :wallet
end
class Follow < ApplicationRecord
belongs_to :project
belongs_to :wallet
end
class Wallet < ApplicationRecord
has_many :permissions
has_many :projects, through: :permissions
has_many :follows
has_many :projects, through: :follows
end
As you can see, Permission and Follow are both through associations for Projects and Wallets.
They serve different purposes (Permission gives Wallets access to manage Projects while Follow lets Wallets "follow" projects for updates).
So how can I differentiate them? For example, if I do Wallet.find(1).projects, it defaults to using the "Follow" model...though in some scenarios I'd want it to actually use the "Permission" model.
Believe you'd find it will default to the has_many :projects that is defined last.
Need to give the associations different names, which will require something like ...
class Wallet < ApplicationRecord
has_many :permissions
has_many :projects, through: :permissions
has_many :follows
has_many :follow_projects, through: :follows, source: :project
end
I need help to achieve something.
Is it possible that my Analysis has_many :klasses, through: :subjects, but filtered using attributes from the join table AnalysisSubject? Or my models should be different?
class Analysis
has_many :analysis_subjects, dependent: :destroy
has_many :subjects, through: :analysis_subjects
has_many :klasses, -> { where(year: ??????, semester: ??????), through: :subjects
end
class AnalysisSubject
belongs_to :analysis
belongs_to :subject
# There are year:integer and semester:integer attributes
# I want to use those attributes in my where clause for analysis.klasses
end
class Subject
has_many :klasses
has_many :analysis_subjects
has_many :analyses, through: :analysis_subjects
end
class Klass
belongs_to :subject
end
I'm using Rails 5 if it is important. Thank you for your help.
Yes, but you should afford it in a different way: You must declare the where in a has_many :filtered_analysis_subjects.
class Analysis
has_many :filtered_analisys_subjects, -> { where(year: x, semester: y }, foreign_key: "analysis_id", class_name: "AnalysisSubject", dependent: :destroy
has_many :subjects, through: :filtered_analysis_subjects
has_many :klasses, through: :subjects
I am implementig the system that enable user to follow the "followable"( in my case these may be an event, place or other user).
My idea:
Follow model holds the user_id, followable type and followale_id(join table)
class Follow < ActiveRecord::Base
belongs_to :user
belongs_to :followable, polymorphic: true
end
Event
class Event < ActiveRecord::Base
has_many :follows, as: :followable
has_many :users, through: :follows
end
Place
class Place < ActiveRecord::Base
has_many :follows, as: :followable
has_many :users, through: :follows
end
User
class User < ActiveRecord::Base
has_many :follows
has_many :events, through: :follows, source: :followable, source_type: "Event"
has_many :places, through: :follows, source: :followable, source_type: "Place"
has_many :users, through: :follows, source: :followable, source_type: "User"
end
The problem is that the realtion works only in one direction, i can do:
user.follows.create(followable:event1) #follow event1
user.follows.create(followable:place1) #follow place1
user.follows.create(followable:user1) #follow user1
user.follows # displays all following relations user has established
But, i cannot do:
event1.follows #return follow objects(some user - event1 pairs)
event1.users #return all of the users that follow this event
user1.users #return all of the users that user1 follows, the most confusing part..
All of the aboves return nil.
How should i establish the relations to make it work in both directions?
Also, i'd like to hear some remarks on how to improve this idea, beacouse it's the first time i'm playin around with more complex realtions.
Thank you in advance.
Lets start off with the User model as its the trickiest:
class User < ActiveRecord::Base
has_many :follows, source: :user
has_many :follows_as_fallowable,
class_name: 'Follow',
as: :followable
has_many :followers, through: :follows_as_fallowable,
source: :user
# other users the user is following
has_many :followed_users, through: :follows,
source: :followable,
source_type: 'User'
end
Note that we need two different relationships to follows due to the fact that the user can be in either column depending on if the user is the follower or the object being followed.
We can now do a simple test to check if the relationship is setup properly:
joe = User.create(name: 'Joe')
jill = User.create(name: 'Jill')
joe.followers << jill
jill.followed_users.include?(joe) # true
joe.followers.include?(jill) # true
To then setup a the bi-directional relation between users and a followable model you would do:
class Event < ActiveRecord::Base
has_many :follows, as: :followable
has_many :followers, through: :follows,
source: :user
end
class User < ActiveRecord::Base
# ...
has_many :followed_events, through: :follows,
source: :followable,
source_type: 'Event'
end
The relations in the followed model (Event) are pretty much the same in every model so you can easily extract it to a module for reuse:
# app/models/concerns/followable.rb
module Followable
extend ActiveSupport::Concern
included do
has_many :follows, as: :followable
has_many :followers, through: :follows,
source: :user
end
end
class Event < ActiceRecord::Base
include Followable
end
class Place < ActiceRecord::Base
include Followable
end
What am trying to do is:
i have a User model and i have a Task model
Task has 2 types of users Owners and Supervisors all of them are users !
so what i have so far is:
Task Model
class Task < ActiveRecord::Base
has_many :task_owners, dependent: :destroy
has_many :task_supervisors, dependent: :destroy
has_many :users, through: :task_owners
has_many :users, through: :task_supervisors
end
TaskSupervisor Model
class TaskSupervisor < ActiveRecord::Base
belongs_to :task
belongs_to :user
end
TaskOwner Model
class TaskOwner < ActiveRecord::Base
belongs_to :task
belongs_to :user
end
and finally the User Model
class User < ActiveRecord::Base
has_many :task_owners
has_many :task_supervisors
has_many :tasks, through: :task_owners
has_many :tasks, through: :task_supervisors
end
now as you can imagine ... my problem is when i get a task and retrieve the users i only get one of my associations ... what i need is a way to change the getters name or identify them some how basically to be able to say something like
task.owners
task.supervisors
class Task < ActiveRecord::Base
has_many :task_owners, dependent: :destroy
has_many :task_supervisors, dependent: :destroy
has_many :owners, through: :task_owners, source: :users
has_many :supervisors, through: :task_supervisors, source: :users
end
You should be able to do this.
Then you should get your task.owners and task.supervisors
Edit:
You will need to change your user model to
class User < ActiveRecord::Base
has_many :task_owners
has_many :task_supervisors
has_many :owned_tasks, through: :task_owners, source: :tasks
has_many :supervised_tasks, through: :task_supervisors, source: :tasks
end
Models:
class User < ActiveRecord::Base
has_many :reports
has_many :social_accounts
has_one :api_client
has_many :integrations
has_many :profiles, through: :integrations
has_many :tags
has_many :profiles, through: :tags
end
class Tag < ActiveRecord::Base
belongs_to :user
belongs_to :profile
end
class Profile < ActiveRecord::Base
has_many :integration_profiles
has_many :integrations, through: :integration_profiles
has_many :users, through: :integrations
belongs_to :api_client
has_many :tags
ene
At times I want to retrieve all of the user's profiles through the integrations and other times through tags. How?
The answer:
has_many :profiles_tagged, through: :tags, source: :profile
On the User model