How do I send two parameters with one link in Rails? - ruby

I am working in a Rails evoting app.
I have the following models: User, Election, Contestant.
I want to allow multiple users vote for contestants in a particular election, and when the user has voted in that election the links to each users should be hidden.
This association is so complicated that I can't get it right.
These are my associations:
class User < ActiveRecord::Base
has_many :contestants
has_many :contestant_votes
end
class Contestant < ActiveRecord::Base
mount_uploader :avatar, AvatarUploader
belongs_to :user
has_many :contestant_votes
has_many :elections
def votes
read_attribute(:votes) || contestant_votes.sum(:value)
end
end
class Election < ActiveRecord::Base
has_many :contestants
end
How do I hide the voting link if the current user has voted for a contestant in an election?

You can just add a uniqueness constraint on contestant_votes. Then you can add a logic to check if there is a contestant_vote between the current user and the contestant.

Related

How to properly handle multiple model associations to different keys in Rails 4.0.8

I'm having the following problem while trying to model my application, it's basically a functionality to handle bills with multiple people, like sharing the rent or any other similar stuff, the deal is:
I have a user model and a billing model but can't find out how to build the associations.
A user has_many billings and billings belongs_to user but, also the billing has_many users, e.g. Tom registers a bill that is meant to be shared by Tom himself, Betty and Bob.
So that makes Tom the creditor and the other two become debtors in the billing.
I'm kinda lost at this point, how to consolidate these associations, dunno if any more information is needed or if it's clear enough, but will appreciate any help and update with any other information needed.
Thanks in advance,
---EDIT---
I've come to the following approach:
Class User < ActiveRecord::Base
has_many :billings, foreign_key: "creditor_id", dependent: :destroy
end
Class Billing < ActiveRecord::Base
belongs_to :creditor, class_name: "User"
has_many :debts, dependent: :destroy
end
Class Debt < ActiveRecord::Base
belongs_to :billing
has_one :user
end
I also tried to graphically model it for better understanding here: imgur
Would that all be correct?
Don't be afraid to use the options available to you in ActiveRecord. If your model naming is getting cluttered (Billing belongs to a User and has_many Users) then be more specific with the association labels and sort the links with options. The Rails Associations Guide is easy to Google and covers pretty much everything.
class User < ActiveRecord::Base
has_many :billings, :foreign_key => 'creditor_id'
has_many :debts, :through => :debtor_users, :source => :billing
end
class Billing < ActiveRecord::Base
belongs_to :creditor, :class_name => 'User'
has_many :debtors, :through => :debtor_users, :source => :user
end
class DebtorUser < ActiveRecord::Base
belongs_to :billing
belongs_to :user
end
You can extend the Billing model to have multiple creditors also simply by converting the belongs_to association into a has_many :through association following the same pattern as debtors just with a different join model (say CreditorUser).

Active Record has_many through more than one model

Is it possible to access objects more than one model away?
For example let's say I have
class Contact <ActiveRecord:Base
has_many :interactions
end
class Interaction <ActiveRecord:Base
belongs_to :contact
belongs_to :course_presentation
end
class CoursePresentation <ActiveRecord:Base
has_many: interactions
belongs_to :course
end
class Course <ActiveRecord:Base
has_many :course_presentations
end
Right now I know I could write a through relationship via contacts to course presentations and then get all the course related to all the course presentations or I could do
contact.interactions.map{ |i| i.course_presentation.course }
I would like to be able to pull courses related to a contact directly so ... e.g.
contact.courses
Is this possible?
Yes, I believe so. Just add the following:
class Contact < ActiveRecord::Base
has_many :interactions
has_many :course_presentations, through: :interactions
has_many :courses, through: :course_presentations
end

Rails ActiveRecord has_many issue

I have a User that has many tasks. This is a predefined set of tasks. Each task has a list of requirements that need to be completed for the task to be finished. I have set up 2 has_many through relationships. Here is my code.
class User < ActiveRecord::Base
has_many :user_tasks
has_many :tasks, through: :user_tasks
end
class UserTask < ActiveRecord::Base
belongs_to :user
belongs_to :task
end
class Task < ActiveRecord::Base
has_many :user_tasks
has_many :users, through: :user_tasks
has_many :task_requirements
has_many :requirements, through: :task_requirements
end
class TaskRequirement < ActiveRecord::Base
belongs_to :task
belongs_to :requirement
end
class Requirement < ActiveRecord::Base
has_many :task_requirements
has_many :requirements, through: :tasks
end
This part seems fairly simple, but now I want to capture the date that each requirement is completed and a boolean of whether it is completed or not for each User. I originally tried to put it in the TaskRequirement table, but of course then it was updated for all users, which is not the behavior that I want. So I have 2 questions.
1. Where do I put these fields?
2. what is the best way to access them?
I assume they will go in a join table, but there is no easy way to access the information in the join tables.
Thanks again for all the help.
If each user completes the task requirements independently of whether other users have completed the task, then you need a UserRequirement table to store the associated data items -- the boolean and the completion date.
However, if each requirement has to be completed multiple times by each user, once for every task with which it is associated, then you'd need a join between User and TaskRequirement, or UserTask and Requirement, or User and Task and Requirement.

Setting ids in has_many relationship between three models

A user can create a post. Posts have comments. A comment must belong to both a user and a post, however not necessarily the user who created the post. Is the following the best way to model this:
class User < ActiveRecord::Base
has_many :posts
has_many :comments
end
class Post < ActiveRecord::Base
belongs_to :user
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :user
belongs_to :post
end
If so, what is the best practice for ensuring:
user.comments.new cannot be called. I want all new posts to be created using the post they are associated with.
The id of the user creating the comment is properly set when calling post.comments.new
Otherwise, what is a better way to model this relationship?
Your models are fine.
To set the author of the comment, you'd have to do that in your controller:
#comment = post.comments.new do |c|
c.user = current_user
end
Just don't use user.comments.new. Why do you want to make it impossible to use it?

Ruby on Rails: Associations when a user likes a song

I'm trying to figure out the best way to setup my database and models for the following scenario.
A user can like an infinite number of songs.
A song can be liked once by an infinite number of users.
I have these tables:
songs, users, likes etc... Following RoR conventions.
The table named likes has these foreign keys: user_id, song_id. And also a field named 'time' to save a timestamp when the song was liked.
I'm not sure of how to do this, I would like to be able to use code like this in my controllers:
User.find(1).likes.all
This should not return from the likes table, but join the songs table and output all the songs that the user likes.
What are the best practises to achieve this in Ruby on Rails following their conventions?
Unless you need to act specifically on the likes table data, the model itself is probably not necessary. The relationship is easy:
class User < ActiveRecord::Base
has_and_belongs_to_many :songs
end
class Song < ActiveRecord::Base
has_and_belongs_to_many :users
end
This will join through the currently non-existent song_users table. But since you want it to join through likes you can change each one to this:
has_and_belongs_to_many :songs, :join_table => 'likes'
If you want to be able to call User.find(1).likes and get songs, then change the user's version to this:
class User < ActiveRecord::Base
has_and_belongs_to_many :likes, :join_table => 'likes', :class_name => 'Song'
end
And you could change the songs version to something like this:
class Song < ActiveRecord::Base
has_and_belongs_to_many :liked_by, :join_table => 'likes', :class_name => 'User'
end
This will give you Song.find(1).liked_by.all and give you the users (You could keep it to users if you wanted using the first version)
More details on habtm relationships can be found here: http://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_and_belongs_to_many
Edit to add
If you want to act on the join table for whatever reason (you find yourself needing methods specifically on the join), you can include the model by doing it this way:
class User < ActiveRecord::Base
has_many :songs, :through => :likes
has_many :likes
end
class Like < ActiveRecord::Base
belongs_to :user
belongs_to :song
end
class Song < ActiveRecord::Base
has_many :users, :through => :likes
has_many :likes
end
This will let you do User.find(1).songs.all, but User.find(1).likes.all will give you the join data

Resources