Hi all,
I have a serialized object (of class Goals) in my statistics table. I
store it in the value row of statitics
When I do:
goals = Statistic.find(1).value.goals_against I get
undefined method `goals_against’ for #YAML::Object:0x5584864
(goals_against is a member of Goals)
Someone knows why this happens?
Thanks
Stijn
Would you share your model definitions and the code that you use to
create/save the statistic and goals instances?
Craig
Thanks for the reply,
Please find the models, database and class definition below.
I try to get the goals object like this
@statistics = @event.statistics.find(:all, :include
=> :statistic_definition)
goals_a = @statistics.first.value.goals_against
=> undefined method `goals_against’ for #YAML::Object:0x579cbec
The YAMLvalue in the database is:
— !ruby/object:Goals
goals:
1: 2
goals_against: 2
goals_for: 2
version: 1
The model:
class Statistic < ActiveRecord::Base
belongs_to :event
belongs_to :statistic_definition
serialize :value
end
statitics table
id int(11)
value text
event_id int(11)
statistic_definition_id int(11)
The object I serialize
class Goals
attr_accessor :goals
attr_accessor :goals_for
attr_accessor :goals_against
attr_accessor :penalty_for
attr_accessor :penalty_against
def initialize(goals, goals_against, penalty_for = nil,
penalty_against = nil)
@version = 1
@goals = goals
set_goals_for()
@goals_against = goals_against.to_i
unless penalty_for.nil?
@penalty_for = penalty_for.to_i
@penalty_against = penalty_against.to_i
end
end
private
def set_goals_for
@goals_for = 0
@goals.each_value {|value| @goals_for += value.to_i }
end
end
On Apr 17, 4:00 pm, “Craig D.” [email protected]
I tried something a bit simpler just to see if it would work. Here’s
what I
did.
- create a new rails app (rails blah)
- create the databases (rake db:create:all)
- generate a Statistic model with a value column of type text
(script/generate model statistic value:text)
- run migrations (rake db:migrate)
- create a non-ActiveRecord class named Goals with one attributed named
goals_against
- run the Rails console (script/console) and do the following:
Statistic.create! :value => Goals.new(3)
=> #<Statistic id: 2, value: #<Goals:0x1928960 @goals_against=3>,
created_at: “2008-04-17 13:22:10”, updated_at: “2008-04-17 13:22:10”>
stat = Statistic.find :first
=> #<Statistic id: 2, value: #<Goals:0x1911ddc @goals_against=3>,
created_at: “2008-04-17 13:22:10”, updated_at: “2008-04-17 13:22:10”>
stat.value.goals_against
=> 3
I didn’t have any problems along the way. Other than using simpler
models/classes, nothing jumps out at me as to what you might have done
that’s causing your problem.
Here’s the source code.
class Statistic < ActiveRecord::Base
serialize :value
end
class Goals
attr_accessor :goals_against
def initialize(goals_against)
@goals_against = goals_against
end
end
Here’s the generated schema from db/schema.rb.
ActiveRecord::Schema.define(:version => 1) do
create_table “statistics”, :force => true do |t|
t.text “value”
t.datetime “created_at”
t.datetime “updated_at”
end
end
Let me know how it goes and if there’s anything more I can do.
Regards,
Craig
Many thanks for the help.
I have found some strange behavior:
I use understanding code to first insert a then read a Goals object
from the database
stat = Statistic.new
stat.event_id = 1
stat.statistic_definition_id = 1
stat.value = Goals.new({1 => 1, 2 => 2}, 1)
stat.save
@statistics = @event.statistics.find(:all, :include
=> :statistic_definition)
goals_a = @statistics.first.value.goals_against
When I use above code the deserialization works as it should.
The next time, when I only get the Goals object out of the database
(and not insert it first), deserialization fails. It seems that I have
to insert and read the object in the same request otherwise
deserialization fails.
This sounds very weird and I have no idea what causes this.
Regards,
Stijn
On Apr 17, 7:35 pm, “Craig D.” [email protected]
I found out something more. When I do:
Goals.new({1 => 1, 2 => 2}, 1)
@statistics = @event.statistics.find(:all, :include
=> :statistic_definition)
goals_a = @statistics.first.value.goals_against
it works.
@statistics = @event.statistics.find(:all, :include
=> :statistic_definition)
goals_a = @statistics.first.value.goals_against
I get undefined method `goals_against’ for #YAML::Object:0x539a954
Can it be that the deserializer doesn’t know the Goals object somehow
by default? I put the Goals class file in my Lib directory.
Regards,
Stijn
When I do
it also works. I thus just have to use the Goals class
In the example that I created, I put the Goals class in app/models even
though it’s not an ActiveRecord model. Does putting your Goals class in
app/models make a difference?
Regards,
Craig
Hi Craig,
Putting it in the apps/model solves the problem. I though tough you
should put all your classes in the lib dir.
regards,
Stijn
On Apr 19, 3:00 pm, “Craig D.” [email protected]
I’ve used the lib dir only once for a very simple rake task, but my
impression is that code in the lib dir should be available to the rest
of
the app. If I have a chance to do a little learning, I’ll report back.
Craig