Rails association - multiple model abilities - ruby-on-rails

I have the following where a user can create a newsletter and can also subscribe to a newsletter. Is there a better way to distinguish between these two abilities with associations or can I put the ownership in the subscription model as suggested by: multiple has_many associations in Rails. With this solution how can I code the newsletter model to get the newsletter owner and newsletter subscribers.
Newsletter Model
# fields: id, user_id
has_many :subscriptions
has_many :users, through: :subscriptions
belongs_to :user *i.e. created by a single user*
Subscription Model
# fields: user_id, newsletter_id
belongs_to :newsletter
belongs_to :user
User Model
# fields: id
has_many :subscriptions
has_many :newsletters, through: :subscriptions
has_many :newsletters *i.e. created many newsletters*
has_many :created_newsletters, :through => :subscriptions, *old answer*
:source => :newsletter,
:conditions => ["newsletter.creator = ?", true]

Newsletter Model
has_many :subscriptions
has_many :subscribers, through: :subscriptions, source: :user
belongs_to :creator, class_name: "User", foreign_key: "user_id"
Subscription Model
# fields: user_id, newsletter_id
belongs_to :newsletter
belongs_to :user
User Model
# fields: id
has_many :subscriptions
has_many :subscribed_newsletters, through: :subscriptions, source: :newsletter
has_many :created_newsletters, class_name: "Newsletter", foreign_key: "user_id"
Now you can get subscribers and creator by doing
newsletter.subscribers
newsletter.creator

Related

Trying to 'alias' a polymorphic has_many relationship

I have a User model:
class User < ActiveRecord::Base
has_many :tracks, dependent: :destroy
has_many :tracked_locations, through: :tracks, source: :tracking, source_type: 'Location'
and a Track model (think of it as 'following'):
class Track < ActiveRecord::Base
belongs_to :user
belongs_to :tracking, polymorphic: true
end
The idea here is I will have many models to track / follow so I am using polymorphism. For example I have a Location model:
class Location < ActiveRecord::Base
has_many :tracks, :as => :tracking, :dependent => :destroy
has_many :users, through: :tracks
Now in the console Location.first.users works fine along with User.first.tracked_locations.
Now I will be adding another polymorphic relationship along the lines of Flagged. The user can 'flag' another model with a note etc. So if I add has_many :users, through: :flagged to the Location model for example I need to differentiate between tracking users and flagged users.
I tried:
has_many :tracking_users, through: :tracks, source: :tracking, source_type: 'User'
but I get:
NoMethodError: undefined method `evaluators_for' for #<Location:0x007ff29e5409c8>
Can I even do this or am I missing something simple here?
UPDATE
Based on the answer below I figured it out:
has_many :tracking_users, through: :tracks, class_name: "User", foreign_key: "user_id", source: :user
I'm not 100% on this, but you could try:
has_many :tracking_users, through: :tracks, class_name: "User", foreign_key: "user_id", source: :user
Or you could also just create a class method and do it by hand.
def self.tracking_users
user_ids = tracks.collect(&:user_id)
User.where(id: user_ids)
end
edit: Had a brainfart, changed the "source" up there to :user. That tells what table to actually do the lookup in with the other attribute you've provided. of course it wouldn't be in :tracks

Is it possible to have an association with the same model, but some records have another association to go through?

Kind of a difficult concept to put into a title, but here is the use case:
I have users, the users can either belong to a partner or a customer. A partner can have many customers, but all users have a partner either directly or indirectly. Is there any way to create an association that would allow for partner access on any user regardless of whether or not they are directly related to it?
This is my current setup:
class User < ActiveRecord::Base
has_one :partner, through: :user_join, :source => :userable, :source_type => "Licensee"
has_one :customer, through: :user_join, :source => :userable, :source_type => "Customer"
end
class Partner < ActiveRecord::Base
has_many :customers
has_many :user_joins, as: :userable
has_many :users, through: :user_joins
end
class Customer < ActiveRecord::Base
belongs_to :partner
has_many :user_joins, as: :userable
has_many :users, through: :user_joins
end

Has_many: :through for LineItems - Rails

I have four models:
User
Listing
Order
OrderGroup
User:
has_many :listings
has_many :orders
Listing:
belongs_to :seller, class_name: "User", foreign_key: :user_id
has_many :order_groups, through: :orders
has_many :orders
Order:
has_one :seller, through: :listing
belongs_to :listing
belongs_to :order_group
OrderGroup:
has_many :listings, through: :orders
has_many :orders
has_many :sellers, through: :orders
When I try to pull Order.where(seller: User.find(3)), I get an empty collection. However, when I do Order.last.seller, I get the seller's user_id.
How can I pull Order.where(seller: User.find(3))' ?
You can write query as
Order.joins(:listing).where('listings.user_id = ?', 3)

Polymorphic Associations for Multiple User Roles in Rails

I'm a designer/HTML+CSS dev learning Rails, and I'm having trouble with multiple user roles. My main models are as follows:
Studio
has_many :locations, dependent: :destroy
has_many :events, through: :locations
has_many :teachers, through: :events
Location
belongs_to :studio, :class_name => Studio, :foreign_key => "studio_id"
has_many :events
has_many :teachers, through: :events
Event
belongs_to :location, :class_name => Location, :foreign_key => "location_id"
belongs_to :studio
has_many :teachers
Teacher
belongs_to :event, :class_name => Event, :foreign_key => "event_id"
belongs_to :location
belongs_to :studio
has_one :user, :as => :roleable
accepts_nested_attributes_for :user
User
belongs_to :roleable, :polymorphic => true
The Teacher/User relationship is the tricky bit; I'm not sure if it should be reversed.
Users have basic profile info, Teachers have many details. All users can follow teachers, but teachers can also invite new teachers, and list other teachers as influences. I had this set up as
Teacher
has_many :guests, class_name: "Teacher", foreign_key: "host_id"
belongs_to :host, class_name: "Teacher"
has_many :influences, class_name: "Teacher", foreign_key: "student_id"
belongs_to :student, class_name: "Teacher"
User
has_many :favorites, class_name: "User", foreign_key: "fan_id"
belongs_to :fan, class_name: "User"
Does this look right, or should I say that User has_one :teacher ? The latter seems more correct, but it made my views really difficult. Thanks in advance!

How to define CanCan abilities with model associations

I'm using CanCan to define abilities in my app.
Question is how to define ability of a model that belongs to the User through an association.
For example this works because Campaign has an affiliate_id field
can :manage, Campaign, :affiliate_id => affiliate.id
However, Affiliates have Subscriptions and Messages through Keywords. Keywords belong to a Campaign.
All associations are working fine. However I'm not sure how to limit only Subscriptions and Messages to the current_user.
These are my current associations
# affiliate.rb
has_many :keywords, :through => :campaigns
has_many :campaigns
# campaign.rb
belongs_to :affiliate
has_many :keywords
has_many :subscriptions, :through => :keywords
has_many :messages, :through => :subscriptions
# keyword.rb
has_many :subscriptions
has_many :messages
belongs_to :campaign
# message.rb
belongs_to :user
belongs_to :campaign
belongs_to :subscription
belongs_to :keyword
# subscription.rb
belongs_to :campaign
belongs_to :affiliate
belongs_to :keyword
has_many :messages
Also, (bonus question), how can I show all objects if the user is admin? I have something like this but It's not retrieving all objects.
if affiliate.status == "admin"
can :manage, :all
end

Resources