Rails: Saving an object into DB

I asked this in the Rails mailing list but nobody answered me, I think
it is a newbie (I am a newbie) error but
I don’t see the light.

In a view I have a link to a controller’s action
(TeamController#add_player) that calls to Player.create_player method,
that initialize a player object then try to save it, but when it calls
to save method an error happens:

NoMethodError in TeamController#add_player

You have a nil object when you didn’t expect it!
The error occured while evaluating nil.keys

/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1557:in
attribute_names' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:2060:inclone_attributes’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1519:in
attributes' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1945:inattributes_with_quotes’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1725:in
update_without_lock' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/locking.rb:33:inupdate_without_callbacks’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/callbacks.rb:274:in
update_without_timestamps' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/timestamp.rb:39:inupdate’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1718:in
create_or_update_without_callbacks' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/callbacks.rb:249:increate_or_update’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1392:in
save_without_validation' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/validations.rb:724:insave_without_transactions’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/transactions.rb:126:in
save' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/connection_adapters/abstract/database_statements.rb:51:intransaction’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/transactions.rb:91:in
transaction' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/transactions.rb:118:intransaction’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/transactions.rb:126:in
save' #{RAILS_ROOT}/app/models/player.rb:15:increate_player’
app/controllers/team_controller.rb:53:in `add_player’

And my Player model is:

class Player < ActiveRecord::Base
belongs_to :team

Crea un jugador con los valores por defecto

def Player.create_player(team_id)
player = Player.new
player.relate_to_team(team_id)
player.save <-------------------------------- LINE 15
return player
end

Relaciona el jugador con un equipo

def relate_to_team(team_id)
@team_id = team_id
end
end

What means that error? Anybody knows what I’m doing wrong?

player.save <-------------------------------- LINE 15

try @player.save

try @player.save

I’ve changed the code to:

def Player.create_player(team_id)
@player = Player.new
@player.relate_to_team(team_id)
@player.save
return @player
end

but get the same error.

After some changes, same error. I don’t understand anything, I have a
model class Player, a table players and the only
thing I want to do is create a new player and save it in the database. I
have another models and when I save them
through a view generated by Rails it works fine.

/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1557:in
attribute_names' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:2060:inclone_attributes’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1519:in
attributes' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1945:inattributes_with_quotes’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1725:in
update_without_lock' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/locking.rb:33:inupdate_without_callbacks’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/callbacks.rb:274:in
update_without_timestamps' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/timestamp.rb:39:inupdate’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1718:in
create_or_update_without_callbacks' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/callbacks.rb:249:increate_or_update’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/base.rb:1392:in
save_without_validation' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/validations.rb:724:insave_without_transactions’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/transactions.rb:126:in
save' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/connection_adapters/abstract/database_statements.rb:51:intransaction’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/transactions.rb:91:in
transaction' /usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/transactions.rb:118:intransaction’
/usr/lib/ruby/gems/1.8/gems/activerecord-1.14.3/lib/active_record/transactions.rb:126:in
save' #{RAILS_ROOT}/app/models/player.rb:21:increate_player’
app/controllers/team_controller.rb:53:in `add_player’

I’ve added some accessors because I don’t know if they are needed by
ActiveRecord, but nothing changes.

class Player < ActiveRecord::Base
attr_reader :team_id, :name, :age, :goal, :defence, :stamina,
:goalkeeper,
:playmaking, :pass, :shot, :speed, :head, :creativity,
:free_kicks,
:captain, :mood, :aggresiveness
attr_writer :team_id, :name, :age, :goal, :defence, :stamina,
:goalkeeper,
:playmaking, :pass, :shot, :speed, :head, :creativity,
:free_kicks,
:captain, :mood, :aggresiveness
belongs_to :team

def initialize
# De momento ponemos cualquier cosa, un numero aleatorio como
cadena
@name = (rand * 1000000).truncate.to_s
# Edad entre 20 y 34 años
@age = rand(34) + 1 + 20
end

Crea un jugador con los valores por defecto

def Player.create_player(team_id)
player = Player.new
player.team_id = team_id
player.save
end

Relaciona el jugador con un equipo

def relate_to_team(team_id)
@team_id = team_id
end
end

On 7/19/06, Kev J. [email protected] wrote:

player.save <-------------------------------- LINE 15

try @player.save

Why do you think that would work? @player isn’t defined.

And for the original question. I have no idea if this will work, but
from my experience with ActiveRecord it might help.

Firstly, what’s with relate_to_team? Just use team_id =, ActiveRecord
does tricky things in the background, so always use the accessors.

Secondly, just so you know, you don’t need the return on the last line

  • the result of the last evaluated expression is always returned, so
    for example:
    def two_plus_one
    2+1
    end

x = two_plus_one
=> x = 3

class Player < ActiveRecord::Base
belongs_to :team

def Player.create_player(team_id)
player = Player.new
player.team_id = team_id
player.save
player # The last evaluated line in a Ruby method is automatically
returned
end
end

I’ve added some accessors because I don’t know if they are needed by ActiveRecord, but nothing changes.

Think of ActiveRecord as magic. It constructs the class and all
attributes from the DB at runtime. When working with ActiveRecord
never use attr_accessor and its like for DB attributes. Also, always
use the automatically created ActiveRecord accessors, eg name = “1234”
rather than @name = “1234”.

I suspect that player might be used by ActiveRecord, try using
new_player as the variable name instead.

it’s already there:

class Team < ActiveRecord::Base
has_many :players

end

team = Team.find(4711)
player = team.players.create

-------- Original-Nachricht --------
Datum: Wed, 19 Jul 2006 19:06:16 +0900
Von: Phillip H. [email protected]
An: [email protected]
Betreff: Re: Rails: Saving an object into DB

          :captain, :mood, :aggresiveness

cadena

Relaciona el jugador con un equipo

def relate_to_team(team_id)
@team_id = team_id
end
end

just try

class Player < ActiveRecord::Base
belongs_to :team
end

1 - you don’t need to specify properties, ActiveRecord gets them from
the table definition, so no attr_reader etc
2 - you don’t need to add a method to save the player, as it inherits
all the methods from ActiveRecord

If you can save a standard ActiveRecord-based object, then you can
change it and add instance/class methods later

Thanks to all for the answers, finally I’ve got it working fine

Eduardo Yáñez Parareda wrote:

def relate_to_team(team_id)
@team_id = team_id
end

This won’t work. Try “self.team_id = team_id” if you want to do this.
team_id is not an instance variable, it’s a special field managed by
ActiveRecord. ActiveRecord also provides read_attribute(:my_attr) and
write_attribute(:my_attr, a_value) if you can’t call its field accessor
functions or want to overwrite them.

May I also suggest just using:

Player.create :team => the_team

There’s no need to write many small functions like this when their
equivalents already exist.