[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.ruby

Rails: Saving an object into DB

EdUarDo

7/19/2006 9:06:00 AM

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?

9 Answers

Kev Jackson

7/19/2006 9:56:00 AM

0

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


--
"In vain you tell me that Artificial Government is good, but that I
fall out with the Abuse. The Thing! The Thing itself is the Abuse!" -
Edmund Burke


EdUarDo

7/19/2006 9:58:00 AM

0

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

Phillip Hutchings

7/19/2006 10:06:00 AM

0

On 7/19/06, Kev Jackson <foamdino@gmail.com> wrote:
> >
> > 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

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

--
Phillip Hutchings
http://www.sit...

EdUarDo

7/19/2006 10:30:00 AM

0

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

Pete

7/19/2006 11:46:00 AM

0

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 <sitharus@sitharus.com>
An: ruby-talk@ruby-lang.org
Betreff: Re: Rails: Saving an object into DB

> On 7/19/06, Kev Jackson <foamdino@gmail.com> wrote:
> > >
> > > 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
>
> 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
>
> --
> Phillip Hutchings
> http://www.sit...

Phillip Hutchings

7/19/2006 8:26:00 PM

0

> 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.
--
Phillip Hutchings
http://www.sit...

Timothy Goddard

7/19/2006 10:06:00 PM

0


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.

Kev Jackson

7/20/2006 1:19:00 AM

0

>
> 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, :goalkee
> per,
> :playmaking, :pass, :shot, :speed, :head, :creativity, :
> free_kicks,
> :captain, :mood, :aggresiveness
>
> attr_writer :team_id, :name, :age, :goal, :defence, :stamina, :goalkee
> per,
> :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
>

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

--
"Man is truly free only among equally free men" - Michael Bakunin


EdUarDo

7/20/2006 10:21:00 AM

0

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