Struggling with has_many :through - ruby-on-rails

Suppose I have 3 Models like this (not sure if this is correct):
class User < ActiveRecord::Base
has_many :lessons
has_many :points, through: :progress
end
class Progress < ActiveRecord::Base
belongs_to :user
has_many :lessons
end
class Lesson < ActiveRecord::Base
belongs_to :progress
end
(The Progress table has user_id and lesson_id fields.)
How would I make it so calling #user.points would return the amount of entries into the Progress table. Also, how would I build a relationship?

class User < ActiveRecord::Base
has_many :progresses
has_many :lessons, through: :progresses
end
class Progress < ActiveRecord::Base
belongs_to :user
belongs_to :lesson
end
class Lesson < ActiveRecord::Base
has_many :progresses
end

First, you need to set up the association for progress on your User model, so that the through association will work:
class User < ActiveRecord::Base
has_many :lessons
has_many :progress
has_many :points, through: :progress
end
Then you'll need to define a method (or relation) of points on your Progress table. Or, if you simply want a count of records, you could do: #user.points.size

Related

Find records that have two exact instances of a many-to-many relation

I have an application with a business logic concerning products with multiple variants:
class Task < ApplicationRecord
belongs_to :variant
end
class Variant < ApplicationRecord
belongs_to :product
has_many :variant_option_values
has_many :option_values, through: :variant_option_values
has_many :prices
end
class Product < ApplicationRecord
has_many :product_option_types
has_many :option_types, through: :product_option_types
has_many :variants
end
class OptionValue < ApplicationRecord
belongs_to :option_type
end
class OptionType < ApplicationRecord
has_many :product_option_types
has_many :products, through: :product_option_types
has_many :option_values
end
class ProductOptionType < ApplicationRecord
belongs_to :product
belongs_to :option_type
end
class VariantOptionValue < ApplicationRecord
belongs_to :variant
belongs_to :option_value
end
The ERD looks like this:
Having a product product_1 how can I find its variants that have OptionValue instances option_value_1, option_value_2 and option_value_3? Note that the variant has to have all three option values at the same time and can have more than those three (but not necessarily).
option_values = [option_value_1, option_value_2, option_value_3]
Variant.include(product: [option_types: :option_values])
.where("option_values.id IN (?)", option_values.map(&:id))
.group("products.id")
.having("count(*) >= ?", option_values.size)

How to correctly set up model associations

I want a user to be able to create and save or choose an existing client to add to an invoice. There can only be one client per invoice.
I currently have 3 models users invoices and items
I am using a simple has_many relationship currently but I am getting confused now that I want to add a new table clients. I was hoping I could get some advice on what association to use.
My current associations
class User < ActiveRecord::Base
has_many :invoices
class Invoice < ActiveRecord::Base
belongs_to :user
has_many :items, :dependent => :destroy
class Item < ActiveRecord::Base
belongs_to :invoice
So I was thinking to do something simple like adding has_many :clients
to users, add has_one :client to invoices and add the table clients
class User < ActiveRecord::Base
has_many :invoices
has_many :clients
class Client < ActiveRecord::Base
belongs_to : user
class Invoice < ActiveRecord::Base
belongs_to :user
has_many :items, :dependent => :destroy
has_one :client
Would this work? Is there a better way?
It is very rare that you will use has_one. In your case the following models make more sense:
class User < ActiveRecord::Base
has_many :invoices
end
class Invoice < ActiveRecord::Base
belongs_to :user
belongs_to :client
has_many :items, :dependent => :destroy
end
class Item < ActiveRecord::Base
belongs_to :invoice
end
class Client < ActiveRecord::Base
has_many :invoices
has_many :items, through: :invoices
end

Activerecord proper associations

I have four models
Bid Order User Printer
currently I cannot access the order through anything except User.
I would like to be able to do something of the sort bid.order but have yet to figure out the correct association. Any thoughts?
class Bid < ActiveRecord::Base
belongs_to :printer
end
class Order < ActiveRecord::Base
belongs_to :user
has_many :bids
end
class Printer < ActiveRecord::Base
has_many :orders, through: :bids
has_many :bids
end
class User < ActiveRecord::Base
has_many :orders
end
Both models must know about the relationship so you need to state that in the Bid model
class Bid < ActiveRecord::Base
belongs_to :printer
belongs_to :order
end

Modeling "Likes" in rails HABTM vs HM/BT

What would be the best method to model "likes" in rails for my app. I could either to the following:
class User < ActiveRecord::Base
has_many :things
has_many :likes
has_many :liked_things, through: :likes, source: :thing
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :thing
end
class Thing < ActiveRecord::Base
belongs_to :user
has_many :likes
has_many :liking_users, through: :likes, source: :user
end
Or
class User < ActiveRecord::Base
has_many :things
has_and_belongs_to_many :things
end
class Thing < ActiveRecord::Base
belongs_to :user
has_and_belongs_to_many :users
end
What approach would be best and why? I plan to have an activity feed in my app as well, if that helps determine the best approach.
The answer to this question depends on whether or not Like will ever have any attributes or methods.
If its only purpose of existence is to be the HABTM relationship between Users and Things, then using the has_and_belongs_to_many relationship would suffice. In your example, having has_many and belongs_to is redundant. All you would need in this case is:
class User < ActiveRecord::Base
has_and_belongs_to_many :things
end
class Thing < ActiveRecord::Base
has_and_belongs_to_many :users
end
On the other hand, if you anticipate that a Like will have an attribute (e.g. maybe someone will really like something, or love it, etc.) then you can do
class User < ActiveRecord::Base
has_many :likes
has_many :liked_things, through: :likes, source: :thing
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :thing
end
class Thing < ActiveRecord::Base
has_many :likes
has_many :liking_users, through: :likes, source: :user
end
Note that I removed has_many :things and belongs_to :user as they are redundant.

Model associations for a contest

I'm new to rails and working on an app that has the following situation:
Users have skills (e.g rafting, dancing)
Users participate in contests
Contest measures multiple skills
At the end of each contest, each user gets a score (e.g dancing: 5, rafting: 4)
Whats the best way to model this ?
Thanks,
This got nasty :s At the end I was actually not sure if this is the right way
class Skill < ActiveRecord::Base
has_many :skill_scores
has_many :user_skills
end
class UserSkill < ActiveRecord::Base
belongs_to :user
belongs_to :skill
end
class SkillScore < ActiveRecord::Base
belongs_to :user
belongs_to :contest
belongs_to :skill
end
class User < ActiveRecord::Base
has_many :skills
has_many :contests, :through => :contest_participations
has_many :skill_scores
end
class Contest < ActiveRecord::Base
has_many :users, :through => :contest_participations
has_many :skill_scores
end
class ContestParticipation < ActiveRecord::Base
belongs_to :user
belongs_to :contest
end

Resources