Rails table join with extra details doesn't work - ruby-on-rails

I have these 2 models, and I'm trying to add an association between them so I can add some extra details later:
class Ticket < ActiveRecord::Base
belongs_to :user
has_many :event_tickets
has_many :events, :through => :event_tickets
end
class Event < ActiveRecord::Base
has_many :event_tickets
has_many :tickets, :through => :event_tickets
end
class EventTicket < ActiveRecord::Base
belongs_to :event
belongs_to :ticket
end
I've tried adding an association like this, just to see it's working:
event_ticket = EventTicket.new(:ticket => ticket, :event => Event.all[0])
event_ticket.save!
This gives me:
can't write unknown attribute `ticket_id`
The ticket and event exist and are working fine, but can't get the event_ticket object working.
What am I doing wrong?

It sounds like you don't have an event_tickets table, or at least it doesn't have a ticket_id column. Are you sure you wrote the migration and ran it?

Related

rails one to-many two sided relation

I wonder how to do the following in Rails in the right way.
I have class Order
class Order < ActiveRecord::Base
has_many :bids, :dependent => :destroy
belongs_to :user
end
and class Bid
class Bid < ActiveRecord::Base
belongs_to :order
end
The following works perfectly fine,
order = Order.find(1)
order.bids
However sometimes I want to get order by bid
order = bid.order
And of course backwards it doesn't work
In addition I want the following to be OK
bid.order.user.username
What the best way to do in Rails?
The order = bid.order should work. Not sure why it happens.
bid.order.user.username
To call this,
you can probably try
class Bid < ActiveRecord::Base
belongs_to :order
has_one :user, :through => :order
end
and call
bid.user.username

How do I assign items that belong to one half of "has many :through" with the other half of the association?

I'm trying to model my database in Ruby and can't figure out how to do it.
This is what I have so far:
class Course < ActiveRecord::Base
has_many :enrolled_ins
has_many :users, :through => :enrolled_ins
has_many :events, :dependent => :destroy
end
class User < ActiveRecord::Base
has_many :enrolled_ins
has_many :courses, :through => :enrolled_ins
end
class EnrolledIn < ActiveRecord::Base
belongs_to :users
belongs_to :courses
end
class Event < ActiveRecord::Base
belongs_to :courses
end
I want to add that when a user picks a course, they can select the different events that they want with that course, and those are assigned to them instead of them getting all the events.
I would add a UserEvents join. When you add a course, you would see a list of available events. Assuming you have a form with checkboxes, you would create the UserEvent records. I don't think you would need all 3 ID values (user, event, course). Course is just a way to group the various events.
class UserEvent < ActiveRecord::Base
belongs_to :user
belongs_to :event
end
I'd also add a dependent destroy on user and on event do destroy the join records if either side is removed.

rails 3.1, how to calculate answers number using foreign key?

I have the following tables:
class FinalExam < ActiveRecord::Base
belongs_to :course
has_many :pages, :as => :course_unit, :dependent => :destroy
end
class Page < ActiveRecord::Base
belongs_to :course_unit, :polymorphic => true
has_one :quiz
has_one :slide
end
class Quiz < ActiveRecord::Base
belongs_to :page
end
class Answers < ActiveRecord::Base
belongs_to :quiz
end
So, we have Answer.Quiz.Page.FinalExam
Given the FianlExam id, what is the fastest way to find all Answers count ? how to get it ?
I can re-design the DB to have belongs_to :final_exam in Answers
class Answers < ActiveRecord::Base
belongs_to :quiz
belongs_to :final_exam
end
this way, I can say Answers.where(:final_exam_id=> params[:id]).count
Do I have to change the DB design ? or its a matter of a query ?
I need an expert advice please.
First of all I'm guessing that Quiz should read:
class Quiz < ActiveRecord::Base
belongs_to :page
has_many :answers
end
If so you can add these lines to your FinalExam model:
has_many :quizzes, :through => :pages
has_many :answers, :through => :quizzes
Allowing you to then call
FinalExam.first.answer.count
(Note: if you're on a version of Rails < 3.1, you'll need this plugin)
The drawback to this approach is that it becomes slow with a lot of data. In this case, you'd want to set up a counter cache in the FinalExam that updates every time an answer is added. It'd a little more complicated because of the many-layered relationships you have; see this post for more info:
counter_cache has_many_through sql optimisation, reduce number of sql queries

Rails has_many :through and has_one :through associations

First I'm using Rails 3.1 from the 3-1-stable branch updated an hour ago.
I'm developing an application where I have 3 essential models User, Company and Job, Here's the relevant part of the models:
class User < ActiveRecord::Base
has_many :companies_users, class_name: "CompaniesUsers"
has_many :companies, :through => :companies_users, :source => :company
end
class Company < ActiveRecord::Base
has_many :companies_users, class_name: "CompaniesUsers"
has_many :employees, :through => :companies_users, :source => :user
has_many :jobs, :dependent => :destroy
end
class Job < ActiveRecord::Base
belongs_to :company, :counter_cache => true
end
class CompaniesUsers < ActiveRecord::Base
belongs_to :company
belongs_to :user
end
The code works just fine, but I have been wondering if it's possible to:
I want to link a job with an employer, so think of this scenario: A user John who's an employee at Example, he posted the job Rails Developer, so I want to access #job.employer and it should get me back the user John, in other words:
#user = User.find_by_name('john')
#job = Job.find(1)
#job.employer == #user #=> true
So I thought of two possible solutions
First solution
class Job
has_one :employer, :through => :employers
end
class User
has_many :jobs, :through => :employers
end
class Employer
belongs_to :job
belongs_to :user
end
Second solution
class Job
has_one :employer, :class_name => "User"
end
class User
belongs_to :job
end
Which route should I go? Is my code right ?
I have another question, how to get rid of the class_name => "CompaniesUsers" option passed to has_many, should the class be Singular or Plural ? Should I rename it to something like Employees ?
P.S: I posted the same question to Ruby on Rails: Talk
Unless I'm missing something, I'd suggest simply doing
class Job
belongs_to :employer, :class_name => "User"
end
class User
has_many :jobs
end
This would give you methods like
user = User.first
user.jobs.create(params)
user.jobs # array
job = user.jobs.first
job.employer == user # true
You'll need an employer_id integer field in your Jobs table for this to work.
Typically you want to name your pass through model:
company_user
Then you don't need this:
class_name: "CompaniesUsers"
Just make sure the name of your database table is:
company_users
What you have works for you, so that's great. I just find when I don't follow convention I
run in to trouble down the road.

Active Record Associations: has_one :through? Or multiple has_one's?

I'm brand new to Rails, so bear with me.
I have 3 models: User, Section, and Tick.
Each section is created by a user. My guess with this association:
class Section < ActiveRecord::Base
has_one :user
end
Next, each user can "tick" off a section -- only once. So for each tick, I have a section_id, user_id, and timestamps. Here's where I'm stuck. Does this call for a "has_one :through" association? If so, which direction? If not, then I'm way off.
Which association works here?
Thanks!
This should be right:
class User < AR::Base
has_many :sections #user can have many sections
has_many :ticks, :through => :sections #user has many ticks, but the left outer join goes through sections
end
class Section < AR::Base
belongs_to :user #each section belongs to 1 user
has_many :ticks #each section can have a tick, because of can use has_many
end
class Tick < AR::Base
belongs_to :section #a tick belongs to a section
has_one :user, :through => :sections #belongs_to :through does not exist, use has_one through
end
class User < AR::Base
has_many :ticks
has_many :sections, :through => :ticks
end
class Section < AR::Base
has_many :ticks
has_many :users, :through => :ticks
end
class Tick < AR::Base
belongs_to :user
belongs_to :section
validates_uniqueness_of :user_id, :scope => :section_id
end
Now to find the sections a user ticked you do user.sections, or to find all users who ticked a certain section you do section.users
What you have here is a many-to-many relation (a user can have many sections, and a section can belong to many users), so this requires a join model to associate them. In this case, the Tick model is acting as the join model.
Try Following
class Tick < ActiveRecord::Base
belongs_to :user
belongs_to :section
validates_uniqueness_of :user_id, :scope => :section_id #There is only one user per section
end
Ref This

Resources