views:

58

answers:

2

I am using Rails 3 beta 4.

I have the following models:

class Player < ActiveRecord::Base
has_many :players_items, :dependent => :destroy 
has_many  :items, :through => :players_items
end

class PlayersItem < ActiveRecord::Base
  belongs_to :player 
  belongs_to :item  
end

class Item < ActiveRecord::Base
  has_many :players_items, :dependent => :destroy
  has_many :players, :through =>  :players_items
end

In the players_controller

def items
    @player = Player.find(params[:id])
    @player_items = @player.items
  end

I have the following attributes

--Items Model--
Item_id:Integer
Name:String
Cost:Integer
Description:Text

--PlayersItem Model--
Item_id:Integer
Player_id:Integer
Total:Integer
Traded:Integer

I am trying to print out all the items associated with a player and for each item print out the "Name", "Cost", "Description", "Total", and "Traded" values.

When I call @player_items in the items.html.erb, I can only access the attributes associated with the Item Model and not any of the attributes associated with PlayersItem model.

I am trying to access the attributes from both the items model and players_items model in the same "call" similar to SQL Join Statement like this

SELECT * FROM players_items INNER JOIN items ON players_items.item_id=items.id  
WHERE players_items.player_id = "@player"

Is this possible?

A: 
@player = Player.order("created_at").last
@player.players_items.each do |item|
  puts "#{item.player}: #{item.description} cost:#{item.cost}"
end

Has many through is a little weird. Think of it as a model whose name should (ideally) be descriptive of the relationship between the two other models. So maybe if equipment is being distributed to the players you could call the join model distributions or loans or something. The players_items is the naming convention for join tables which aren't going to be addressed directly. I hope that helps!

Mike Williamson
But wouldn't I need to access the players_items join tables because I have attributes assigned to the join relationship ("total" and "traded")?I am trying to access the attributes from both the items model and players_items model in the same "call" similar to SQL Join Statement like this `SELECT * FROM players_items INNER JOIN items ON players_items.item_id=items.id WHERE players_items.player_id = "@player"`
Joey
A join TABLE is used in a HABTM relation. There are just two fk's and no other columns. What you have is a join MODEL. My understanding is that when you start collecting information about the relation between to models, that relation becomes a "thing" which requires a model. You will need to work with that model to access the info you need. Inside that each block you have access to all of the info you asked for. Its not what you expect when you are used to DBs. Writing a Player.find_by_sqlwill give you what you are expecting (ie a player model with attributes from the players_items table).
Mike Williamson
Ran out of space. FYI, the find_by_sql is not recommended though. I develop in MySQL and deploy to a postgres server. Find_by_sql will make that sort of thing very painful. Use with care.
Mike Williamson
Ok. Maybe I did not setup my model properly because in my PlayersItems join table, I have both the fk's and other attributes that apply to that relationship("total" and "traded"). Is this not the correct way to accomplish adding attributes to the relationship?I followed http://guides.rails.info/association_basics.html Section 2.4 for my model.I don't plan on using the find_by_sql, it was used to signify what I was trying to accomplish.
Joey
Sorry! I think I am confusing you. Give the code I gave you a try. Basically all that is happening is that you are accessing the info you want through the join model rather than through the player model. The code I gave you shows how to do it when you have a player model to work with.
Mike Williamson
A: 

Used in the controller

@player = Player.find(params[:id], :include => [:items,:players_items])

And in the view

@player.players_items.each do |player| 
puts "#{player.name}: #{player.player.item.description} cost:#{player.item.cost}"
end
Joey