I have two models that are associated with has_and_belongs_to_many, and
I'm trying to create a method that computes something with attributes
from both models, but I'm getting an undefined method error with the
code I'm using below. What am I missing?
Model_1.rb
Class Model_1 < ActiveRecord::Base
...
has_and_belongs_to_many :model_2
def some_method
attr_1 * Model_2.find(model_2_id).attr_I_need
end
If the relationship is HABTM, you won't have a model_2_id attribute to
find by, there should be a join table.
If you explain in a little more detail what problem you're trying to
solve with your relationship and the mathematical operation between
them, maybe a solution can be suggested.
I actually have created the join table as documented in the rails
guides, with the right naming convention and all. It's got a model_1_id
and a model_2_id, and an index
Sure, I can give some more details. I'm creating a golf application that
let's users enter in some information about their golf game, and then
shows them appropriate golf courses.
So I've got one model called 'Course' that is just a bunch of seed data.
Then I've got another model called 'Player' that contains all the
user-entered information via a form.
Ultimately, I have a Player 'show' view that shows a table with the
appropriate golf courses, along with some other information. One of
these other pieces of information is a mathematical function that
compares the user's entered handicap with the course's.
So all of my methods are in the Player model, and for this handicap
function, I'm trying to pull in the Course's handicap attribute to do
the math.
I actually have created the join table as documented in the rails
guides, with the right naming convention and all. It's got a model_1_id
and a model_2_id, and an index
Sure, I can give some more details. I'm creating a golf application that
let's users enter in some information about their golf game, and then
shows them appropriate golf courses.
So I've got one model called 'Course' that is just a bunch of seed data.
Then I've got another model called 'Player' that contains all the
user-entered information via a form.
Ultimately, I have a Player 'show' view that shows a table with the
appropriate golf courses, along with some other information. One of
these other pieces of information is a mathematical function that
compares the user's entered handicap with the course's.
So all of my methods are in the Player model, and for this handicap
function, I'm trying to pull in the Course's handicap attribute to do
the math.
Rails provides methods for accessing associations between models. You
should not need to use foreign keys directly as shown in your original
post.
Given:
1. Player has many courses
2. Course has many players
Example:
a_player = Player.first
players_courses = a_player.courses
player_courses.each do |course|
puts course.handicap
end
class Player
def recommended_courses
Course.where(courses[:handicap].gt(a_player.handicap))
.and(courses[:handicap].lt(a_player.handicap)
end
end
These examples are for demonstration only. They are completely untested
or checked for syntax.
class Player
def recommended_courses
Course.where(courses[:handicap].gt(a_player.handicap))
.and(courses[:handicap].lt(a_player.handicap)
end
end
Just realized after posting that this is a silly example, but should get
you on the right track.
Should have been something like ....
courses[:handicap].gt(a_player.handicap -
5).and(courses[:handicap].lt(a_player.handicap + 5))
Sorry I don't know anything about golf, so that may still sound
ridiculous from the perspective of a golf handicap. I hope it at least
helps with the programming issue.
Thanks for the help! Although I'm not sure I totally understand it,
still a bit of a noob. So if I wanted to do something as simple as
subtract the user's handicap from the course's handicap, how would I
create a method for that in the Player model? (sorry maybe you might
have done it already but I'm not sure what .gt and .lt mean)
Basically something like
class Player
def handicaps_difference
Course.handicap - handicap (from the player)
end
Thanks for the help! Although I'm not sure I totally understand it,
still a bit of a noob. So if I wanted to do something as simple as
subtract the user's handicap from the course's handicap, how would I
create a method for that in the Player model? (sorry maybe you might
have done it already but I'm not sure what .gt and .lt mean)
Basically something like
class Player
def handicaps_difference
Course.handicap - handicap (from the player)
end
Given that with a many-to-many relationship (has_and_belongs_to_many) a
single player will be associated to many courses and one course will be
associated to many players. So in order to do that sort of math you'll
need to iterate through them.
Player will have a method, added by ActiveRecord named "courses"...
a_player.courses
I assume here that you want to first select a player:
a_player = Player.find(:id)
Then I assume you want to list all the courses associated with this one
player with the handicap difference:
a_player.courses.each do |course|
puts course.handicap_difference(a_player)
end
Where each course can calculate the handicap difference with a given
player:
class Course
def handicap_different(player)
player.handicap - self.handicap
end
end
But even better would be to expose the join table with its own object
using has_many :through. Then you can put the calculation in the object
that "knows" about both sides:
class CourseAssignment # The exposed join table
has_one :player
has_one :course
def handicap_difference
player.handicap - course.handicap
end
end
Again the "player" and "course" methods will be added by ActiveRecord to
the CourseAssignment object.
Thanks for the help! Although I'm not sure I totally understand it,
still a bit of a noob. So if I wanted to do something as simple as
subtract the user's handicap from the course's handicap, how would I
create a method for that in the Player model? (sorry maybe you might
have done it already but I'm not sure what .gt and .lt mean)
Forgot to mention ".gt" and ".lt" means "greater than" and "less than"
respectively.
Okay great, thanks! I think I'll actually trying doing this in the join
table. I guess my last question would be how would I call that method
from that join table in let's say the Player show view?