Belongs_to too many columns ID - ruby

I'm trying to create a Matches table. This matches table will look to get it's information from a Teams table. I'm having trouble getting the association to work.
class Match < ActiveRecord::Base
#
end
class Team < ActiveRecord::Base
belongs_to :matches, :class_name => "Match", :foreign_key => "hometeam_id"
belongs_to :matches, :class_name => "Match", :foreign_key => "awayteam_id"
end
My Match table has
# id
# hometeam_id
# awayteam_id
# …
My Team table has
# id
# name
# …
I want to be able to do the following
game = Match.find(:first)
# <Match id: 1, hometeam_id: 64810937, awayteam_id: 78380562,
game.hometeam
# returns "Toronto"
I'm not too sure if my belongs_to is the right way to do it. I feel like I'm repeating myself and their might be a better approach. Thoughts?
UPDATE SOLVED
class Match < ActiveRecord::Base
belongs_to :hometeam, :class_name => "Team"
belongs_to :awayteam, :class_name => "Team"
end
class Team < ActiveRecord::Base
has_many :homegames, :class_name => "Match", :foreign_key => "hometeam_id"
has_many :awaygames, :class_name => "Match", :foreign_key => "awayteam_id"
end
Leaving this up for anyone else who runs into similar problems.

Try this:
class Team < ActiveRecord::Base
belongs_to :hometeam, :class_name => "Match", :foreign_key => "hometeam_id"
belongs_to :awayteam, :class_name => "Match", :foreign_key => "awayteam_id"
end

Related

Value of key for Model object gained dynamically

I'm trying to gain a value from an associated table linked via a field in a table using the following (where i is created in an each loop):
value = current_user.question["convq#{i}"].id
My table has references from the Questions table to a Questionsbank table in the form of columns named convq1_id, convq2_id ... convq3_id.
I simply want to cycle through each field in Questions and gain the questionbank.text field.
Sadly, the above will only give me the physical value in the question table field not a link to the associated record using the following code:
(1...9).each do |i|
value = current_user.question["convq#{i}"].id
end
Can anyone let me know how I can cycle through table and gain the associated 'id' or text value of the referenced record?
Thanks in advance.
Each model is set up as:
class Question < ActiveRecord::Base
belongs_to :user
belongs_to :convq1, :class_name => 'Questionbank'
belongs_to :convq2, :class_name => 'Questionbank'
belongs_to :convq3, :class_name => 'Questionbank'
belongs_to :convq4, :class_name => 'Questionbank'
belongs_to :convq5, :class_name => 'Questionbank'
belongs_to :convq6, :class_name => 'Questionbank'
belongs_to :convq7, :class_name => 'Questionbank'
belongs_to :convq8, :class_name => 'Questionbank'
belongs_to :convq9, :class_name => 'Questionbank'
has_many :questionbanks
end
and ...
class Questionbank < ActiveRecord::Base
has_many :likes
has_many :questions
end
I think this is what you might be looking for:
(1...9).each do |i|
value = current_user.question["convq#{i}"]
questionbank = Questionbank.find_by( question: "{value}")
questionbank.id
end

Rails ActiveRecord query for most recent viewed resources

I recently made the following models:
class User < ActiveRecord::Base
has_many :resources
has_many :resource_views, :through => :user_resource_views, :source => 'Resource'
end
class Resource < ActiveRecord::Base
belongs_to :user
has_many :resource_views, :through => :user_resource_views, :source => 'Resource'
end
class UserResourceView < ActiveRecord::Base
attr_accessible :resource_id, :user_id
belongs_to :resource
belongs_to :user_id
end
Now, I want my home#index action to set #resources to the current_user's most recently viewed resources. How would you advise I proceed? Perhaps something similar to current_user.resource_views.find(:all, :order => 'created_at')?
In SQL, I would do something like:
SELECT *
FROM Resource
WHERE id IN (SELECT * FROM UserResourceView WHERE user_id = current_user.id)
... but then the ORDER BY created_at, hmmm
I'll be periodically adding progress updates throughout the day until I figure it out.
Given you're on Rails 3.x, what you're looking for is probably something like this:
class User < ActiveRecord::Base
has_many :resources
has_many :resource_views, :class_name => 'UserResourceView'
has_many :viewed_resources, :through => :resource_views, :source => :resource
def recently_viewed_resources
viewed_resources.order('user_resource_views.created_at DESC')
end
end
class Resource < ActiveRecord::Base
belongs_to :user
has_many :resource_views, :class_name => 'UserResourceView'
end
class UserResourceView < ActiveRecord::Base
attr_accessible :resource_id, :user_id
belongs_to :resource
belongs_to :user_id
end
And to access the collection in your controller:
current_user.recently_viewed_resources

Rails - one model with two associations

I have the model Member that contains all informations about the registered member on my site. Then I have the model Message which contains 2 columns (actually 3 with id):
- member_id
- message_from
In the table Messages are stored IDs of user, how chatting together - when the member A send message to member B, so in the column member_id is saved ID of person A and into the column message_from ID of the person B.
My current associations looks like:
class Member < ActiveRecord::Base
has_many :messages_from
end
class Message < ActiveRecord::Base
belongs_to :member
end
I don't know, how could I get the name of the person stored in the column message_from - when I try
- #member.messages_from.each do |mess_from|
={mess_from.name}
so I get the error undefined method "name" for... How could I get the name of the user through ID that is stored in the column message_from?
EDIT - update relations:
class Member < ActiveRecord::Base
has_many :messages
end
class Message < ActiveRecord::Base
belongs_to :member, :foreign_key => 'user_id', :class_name => 'Member'
has_one :member, :foreign_key => 'message_from', :class_name => 'Member'
end
gives me:
- #member.messages.each do |message|
= message.message_from.inspect # => "110"
= message.message_from.inspect # => undefined method `name' for "110":String (I wanna get the name of person with ID 110)
I'd do something like this:
# Untested code, please check yourself!
class Member < ActiveRecord::Base
has_many :outgoing_messages, :class_name => "Message",
:foreign_key => :message_from_id
has_many :incoming_messages, :class_name => "Message",
:foreign_key => :message_to_id
end
class Message < ActiveRecord::Base
belongs_to :sender, :class_name => "Member",
:foreign_key => :message_from_id
belongs_to :receiver, :class_name => "Member",
:foreign_key => :message_to_id
end
More to read about associations here:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_many
EDIT: In your views:
- #member.outgoing_messages.each do |message|
={message.receiver.name}
={message.sender.name}

Active Record Relation Joins - 3 main tables, 2 join tables

The setup
I have a data model with 3 major tables (users, links, topics) with 2 join tables (link_saves and link_topics). My models:
User
has_many :link_saves, :class_name => 'LinkSave', :foreign_key => 'user_id'
has_many :links, :through => :link_saves
LinkSave
belongs_to :user
belongs_to :link
Link
has_many :link_saves, :class_name => 'LinkSave', :foreign_key => 'link_id'
has_many :users, :through => :link_saves
has_many :link_topics, :inverse_of => :link
has_many :topics, :through => :link_topics
LinkTopic
belongs_to :link
belongs_to :topic
Topic
has_many :link_topics
has_many :links, :through => :link_topics
The Question
I want to be able to find a list of all the topics a user has saved links for. I would like to be able to do #user.topics and have it hop across all 5 tables from user all the way to topics. More importantly, I want this to return an ActiveRecord relation so that I can scope/sort/page the list of user topics further so this would NOT work:
## app/models/user.rb
def topics
links.collect(&:topics)
end
Am I going down the wrong path? Is there a way to do this through active record without having to write all the custom SQL? Help please!
Possible Answers (Update)
Using multiple has_many :throughs to make all the hops. This works, but can't be best practice, right?
## app/models/user.rb
has_many :link_saves, :class_name => 'LinkSave', :foreign_key => 'user_id'
has_many :links, :through => :link_saves
has_many :link_topics, :through => :links, :uniq => true
has_many :topics, :through => :link_topics, :uniq => true
I think this is called a 'nested' has_many through, basically going from A to B to C.
In Rails 3.1 this functionality is now supported
http://www.warmroom.com/yesterdays/2011/08/30/rails-3-1-nested-associations/
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html (search for 'Nested')
The example they have is a bit simpler than what you have, but I think it should be enough for you to get some ideas.
class Author < ActiveRecord::Base
has_many :posts
has_many :comments, :through => :posts
has_many :commenters, :through => :comments
end
class Post < ActiveRecord::Base
has_many :comments
end
class Comment < ActiveRecord::Base
belongs_to :commenter
end
#author = Author.first
#author.commenters # => People who commented on posts written by the author
Prior to Rails 3.1 there was a plugin
'https://github.com/releod/nested_has_many_through'

Rails 3, has_many :through and :polymorphic - Should I need to do this?

Ok so here goes. I don't know if I'm over complicating things or if I'm just still so new to Rails that I don't understand the basics. What I want in sudo code is this:
User
has_many projects as owner through relationship
has_many projects as contributor through relationship
has_many projects as follower through relationship
Project
has_one user as owner through relationship
has_many users as followers through relationship
has_many users as contributors through relationship
Relationship
belongs_to user
belongs_to project
Then I'm wanting to have the following magical things:
owner = Project.owner
followers = Project.followers
contributors = Project.contributors
projects = User.projects
myprojects = User.projects... (now I'm really not sure)
followedProjects = ...
contributingProjects = ...
So in writing that down I can see that there is another gap in my understanding of this model. The users can have the role of owner, follower or contributor or any combination of all three.
In terms of real code I have added here what I think is the relevant parts:
class User < ActiveRecord::Base
has_many :user_project_relationships, :as => :relateable, :class_name => "UserProjectRelationship"
has_many :projects, :as => :owner, :through => :relateable, :class_name => "Project", :source_type => :owner
has_many :projects, :as => :follower, :through => :relateable, :class_name => "Project", :source_type => :follower
has_many :projects, :as => :contributor, :through => :relateable, :class_name => "Project", :source_type => :contributor
end
class Project < ActiveRecord::Base
has_many :user_project_relationships, :as => :relateable, :class_name => "UserProjectRelationship"
has_one :user, :as => :owner, :through => :relateable, :class_name => "User"
has_many :users, :as => :followers, :through => :relateable, :source_type => :follower, :class_name => "User"
has_many :users, :as => :contributors, :through => :relateable, :source_type => :contributor, :class_name => "User"
end
class UserProjectRelationship < ActiveRecord::Base
belongs_to :user
belongs_to :project, :polymorphic => true
end
The migration for the relationships model is:
class CreateUserProjectRelationships < ActiveRecord::Migration
def self.up
create_table :user_project_relationships do |t|
t.integer :relateable_id
t.string :relateable_type
t.integer :project_id
t.timestamps
end
add_index :user_project_relationships, [:relateable_id, :relateable_type], :name => :relateable
add_index :user_project_relationships, :project_id
end
def self.down
drop_table :user_project_relationships
end
end
Currently I get errors for things like project.users ActiveRecord::HasManyThroughAssociationNotFoundError: Could not find the association :relateable in model Project
I feel like I'm too in the wilderness here to really get what I want, and maybe relying on magical rails to do more than it does. Any guidance on the best path would be greatly appreciated.
Thanks in advance
Steve
Rails can do alot, but I think instead you're trying to make the Relationship model do too much. Each of those are a different kind of relationship, so I think try to keep them so.
Split that up into separate join models:
class User < ActiveRecord::Base
has_many :owned_projects, :class_name => "Project", :foreign_key => :owner_id
has_many :projects_followers
has_many :followed_projects, :class_name => "Project", :through => :projects_followers
has_many :projects_contributors
has_many :contributed_projects, :class_name => "Project", :through => :projects_contributors
end
class Project < ActiveRecord::Base
belongs_to :owner
has_many :projects_followers
has_many :followers, :class_name => "User", :through => :projects_followers
has_many :projects_contributors, :foreign_key => :contributor_id
has_many :contributors, :class_name => "User", :through => :projects_contributors
end
class ProjectsFollowers < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
class ProjectsContributors < ActiveRecord::Base
belongs_to :user
belongs_to :project
end
Should be a lot closer to what you want. You can then indeed do
project.owner
project.followers
project.contributors
and
user.owned_projects
user.followed_projects
user.contributed_projects
That should either work, or get you pretty close.
I think your mixup came from trying to make a polymorphic relationship, which I don't think is desireable here. AFAI grok, the use case for polymorphic relationships is when you want 1 Model to be related to Any number of other models in the same way. That's not the case here, as you have 2 models with 3 different types of relationships between them.

Resources