Rails: Saving an object into DB

  • Thread starter Eduardo Yáñez Parareda
  • Start date
E

Eduardo Yáñez Parareda

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:in
`clone_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:in
`attributes_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:in
`update_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:in
`update'
/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:in
`create_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:in
`save_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:in
`transaction'
/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:in
`transaction'
/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:in `create_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?
 
K

Kev Jackson

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

try @player.save
 
E

Eduardo Yáñez Parareda

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.
 
P

Phillip Hutchings

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
 
E

Eduardo Yáñez Parareda

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:in `clone_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:in `attributes_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:in `update_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:in `update'
/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:in `create_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:in `save_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:in
`transaction'
/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:in `transaction'
/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:in `create_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
 
P

Peter Ertl

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 Hutchings <[email protected]>
An: (e-mail address removed)
Betreff: Re: Rails: Saving an object into DB
 
P

Phillip Hutchings

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.
 
T

Timothy Goddard

Eduardo said:
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.
 
K

Kev Jackson

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

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

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

# Crea un jugador con los valores por defecto
def Player.create_player(team_id)
player =3D Player.new
player.team_id =3D team_id
player.save
end

# Relaciona el jugador con un equipo
def relate_to_team(team_id)
@team_id =3D 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 =20=

the table definition, so no attr_reader etc
2 - you don't need to add a method to save the player, as it inherits =20=

all the methods from ActiveRecord

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

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,774
Messages
2,569,599
Members
45,165
Latest member
JavierBrak
Top