简体   繁体   中英

Rails help after update error NoMethodError

I get this error when I have updated my konkurrancer:

Started POST "/konkurrancers/rate/1" for 127.0.0.1 at 2011-05-02 18:52:31 +0200
  Processing by KonkurrancersController#rate as */*
  Parameters: {"utf8"=>"Ô£ô", "authenticity_token"=>"y2ut0YoqeUPT9z/5GBI1SDtzYIW
KjAtRI8fkG2e2Yi0=", "vind"=>{"ratings"=>"6"}, "id"=>"1"}
  ←[1m←[35mSQL (0.0ms)←[0m  describe `kategoris_konkurrancers`
  ←[1m←[36mKonkurrancer Load (0.0ms)←[0m  ←[1mSELECT `konkurrancers`.* FROM `kon
kurrancers`←[0m
  ←[1m←[35mCACHE (0.0ms)←[0m  SELECT `konkurrancers`.* FROM `konkurrancers`
  ←[1m←[36mCACHE (0.0ms)←[0m  ←[1mSELECT `konkurrancers`.* FROM `konkurrancers`←
[0m
  ←[1m←[35mTag Load (0.0ms)←[0m  SELECT `tags`.* FROM `tags`
  ←[1m←[36mSQL (0.0ms)←[0m  ←[1mSELECT COUNT(*) FROM `konkurrancers` INNER JOIN
`tagsmenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmen
us`.tag_id = 11))←[0m
  ←[1m←[35mSQL (0.0ms)←[0m  SELECT COUNT(*) FROM `konkurrancers` INNER JOIN `tag
smenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmenus`.
tag_id = 12))
  ←[1m←[36mSQL (0.0ms)←[0m  ←[1mSELECT COUNT(*) FROM `konkurrancers` INNER JOIN
`tagsmenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmen
us`.tag_id = 13))←[0m
  ←[1m←[35mSQL (0.0ms)←[0m  SELECT COUNT(*) FROM `konkurrancers` INNER JOIN `tag
smenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmenus`.
tag_id = 14))
  ←[1m←[36mSQL (0.0ms)←[0m  ←[1mSELECT COUNT(*) FROM `konkurrancers` INNER JOIN
`tagsmenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmen
us`.tag_id = 15))←[0m
  ←[1m←[35mSQL (0.0ms)←[0m  SELECT COUNT(*) FROM `konkurrancers` INNER JOIN `tag
smenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmenus`.
tag_id = 16))
  ←[1m←[36mSQL (0.0ms)←[0m  ←[1mSELECT COUNT(*) FROM `konkurrancers` INNER JOIN
`tagsmenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmen
us`.tag_id = 20))←[0m
  ←[1m←[35mSQL (0.0ms)←[0m  SELECT COUNT(*) FROM `konkurrancers` INNER JOIN `tag
smenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmenus`.
tag_id = 21))
  ←[1m←[36mSQL (0.0ms)←[0m  ←[1mSELECT COUNT(*) FROM `konkurrancers` INNER JOIN
`tagsmenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmen
us`.tag_id = 22))←[0m
  ←[1m←[35mSQL (0.0ms)←[0m  SELECT COUNT(*) FROM `konkurrancers` INNER JOIN `tag
smenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmenus`.
tag_id = 23))
  ←[1m←[36mSQL (0.0ms)←[0m  ←[1mSELECT COUNT(*) FROM `konkurrancers` INNER JOIN
`tagsmenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmen
us`.tag_id = 24))←[0m
  ←[1m←[35mSQL (0.0ms)←[0m  SELECT COUNT(*) FROM `konkurrancers` INNER JOIN `tag
smenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmenus`.
tag_id = 25))
  ←[1m←[36mSQL (0.0ms)←[0m  ←[1mSELECT COUNT(*) FROM `konkurrancers` INNER JOIN
`tagsmenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmen
us`.tag_id = 26))←[0m
  ←[1m←[35mSQL (0.0ms)←[0m  SELECT COUNT(*) FROM `konkurrancers` INNER JOIN `tag
smenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmenus`.
tag_id = 29))
  ←[1m←[36mSQL (0.0ms)←[0m  ←[1mSELECT COUNT(*) FROM `konkurrancers` INNER JOIN
`tagsmenus` ON `konkurrancers`.id = `tagsmenus`.konkurrancer_id WHERE ((`tagsmen
us`.tag_id = 30))←[0m
  ←[1m←[35mKonkurrancer Load (0.0ms)←[0m  SELECT `konkurrancers`.* FROM `konkurr
ancers` WHERE (`konkurrancers`.`cached_slug` = '1') LIMIT 1
  ←[1m←[36mSQL (0.0ms)←[0m  ←[1mSELECT sluggable_id FROM slugs WHERE ((slugs.slu
ggable_type = 'Konkurrancer' AND slugs.name = '1' AND slugs.sequence = 1))←[0m
  ←[1m←[35mKonkurrancer Load (0.0ms)←[0m  SELECT `konkurrancers`.* FROM `konkurr
ancers` WHERE (`konkurrancers`.`id` = 1) LIMIT 1
Completed   in 390ms

NoMethodError (You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.+):
  app/controllers/konkurrancers_controller.rb:7:in `rate'

Rendered C:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.0.3/lib/action_dispatc
h/middleware/templates/rescues/_trace.erb (15.6ms)
  ←[1m←[36mKonkurrancer Load (0.0ms)←[0m  ←[1mSELECT `konkurrancers`.* FROM `kon
kurrancers` LIMIT 15 OFFSET 0←[0m
  ←[1m←[35mSQL (0.0ms)←[0m  SHOW TABLES
  ←[1m←[36mSQL (0.0ms)←[0m  ←[1mSHOW TABLES←[0m
Rendered C:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.0.3/lib/action_dispatc
h/middleware/templates/rescues/_request_and_response.erb (374.4ms)
Rendered C:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.0.3/lib/action_dispatc
h/middleware/templates/rescues/diagnostics.erb within rescues/layout (421.2ms)

My controller:

class KonkurrancersController < ApplicationController

  def rate
    @konkurrancer = Konkurrancer.find(params[:id])
    @container = "Konkurrancer"+@konkurrancer.id.to_s

    @konkurrancer.rating_score += params[:vind][:ratings].to_i
    @konkurrancer.ratings += 1
    @konkurrancer.save

    respond_to do |format|
      format.js
    end
  end

My model:

class Konkurrancer < ActiveRecord::Base
attr_accessible :ratings, :rating_score, :rating
after_update :do_foobar


def rating
    self[:rating] || (rating_score/rating)
end


 def to_param
    self.name
  end 
    def do_foobar

      rating_score = self.rating_score
      ratings = self.ratings
      rating = (rating_score/ratings)
      self.update_attributes(:rating => rating)

    end

protected
  def assign_cached_slug
    self.cached_slug = self.name.gsub(/\s+/, '_').gsub(/[^\w\-]/, '')
  end
end

My table:

rating_score => The current score
ratings => The number of ratings which led to the score
rating => The current rating

EDIT:

My error:

rancers`.`id` = 1)←[0m
  ←[1m←[35mAREL (1.0ms)←[0m  UPDATE `konkurrancers` SET `rating_score` = 6, `rat
ings` = 1, `updated_at` = '2011-05-02 18:30:45', `rating` = 6 WHERE (`konkurranc
ers`.`id` = 1)
  ←[1m←[36mAREL (1.0ms)←[0m  ←[1mUPDATE `konkurrancers` SET `rating_score` = 6,
`ratings` = 1, `updated_at` = '2011-05-02 18:30:45', `rating` = 6 WHERE (`konkur
rancers`.`id` = 1)←[0m
  ←[1m←[35mAREL (1.0ms)←[0m  UPDATE `konkurrancers` SET `rating_score` = 6, `rat
ings` = 1, `updated_at` = '2011-05-02 18:30:45', `rating` = 6 WHERE (`konkurranc
ers`.`id` = 1)
  ←[1m←[36mSQL (41.0ms)←[0m  ←[1mROLLBACK←[0m
Completed   in 2397ms

SystemStackError (stack level too deep):


Rendered C:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.0.3/lib/action_dispatc
h/middleware/templates/rescues/_trace.erb (2.0ms)
  ←[1m←[35mKonkurrancer Load (1.0ms)←[0m  SELECT `konkurrancers`.* FROM `konkurr
ancers` LIMIT 15 OFFSET 0
  ←[1m←[36mSQL (5.0ms)←[0m  ←[1mSHOW TABLES←[0m
  ←[1m←[35mSQL (5.0ms)←[0m  SHOW TABLES
Rendered C:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.0.3/lib/action_dispatc
h/middleware/templates/rescues/_request_and_response.erb (610.0ms)
Rendered C:/Ruby192/lib/ruby/gems/1.9.1/gems/actionpack-3.0.3/lib/action_dispatc
h/middleware/templates/rescues/diagnostics.erb within rescues/layout (676.0ms)

My model:

class Konkurrancer < ActiveRecord::Base
attr_accessible :ratings, :rating_score, :rating
after_update :do_foobar
after_initialize :init


def rating
    self[:rating] || (rating_score/rating)
end

  def init
    self.rating_score ||= 0
  end



 def to_param
    self.name
  end 
    def do_foobar

      rating_score = self.rating_score
      ratings = self.ratings
      rating = (rating_score/ratings)
      self.update_attributes(:rating => rating)

    end

protected
  def assign_cached_slug
    self.cached_slug = self.name.gsub(/\s+/, '_').gsub(/[^\w\-]/, '')
  end
end



  def tag_tokens=(ids)
    self.tag_ids = ids.split(",")
  end

My controller:

class KonkurrancersController < ApplicationController

  def rate
    @konkurrancer = Konkurrancer.find(params[:id])
    @container = "Konkurrancer"+@konkurrancer.id.to_s
    @konkurrancer.rating_score += params[:vind][:ratings].to_i
    @konkurrancer.ratings += 1
    @konkurrancer.save

    respond_to do |format|
      format.js
    end
  end
end

@konkurrancer.rating_score += params[:vind][:ratings].to_i is failing because @konkurrancer.rating_score is nil.

Try initializing it to something first, maybe 0?

@konkurrancer.rating_score ||= 0
@konkurrancer.rating_score += params[:vind][:ratings].to_i

As BaroqueBobcat mentions below, it's best to put this login in your model:

class Konkurrancer < ActiveRecord::Base
  after_initialize :init

  def init
    self.rating_score ||= 0
  end
end

(See How can I set default values in ActiveRecord? for the reasoning behind using the after_initialize hook).


Regarding your second problem:

In your model, you have after_update:do_foobar , but your do_foobar method updates the model, which triggers after_update:do_foobar again, and this keeps going deeper and deeper (until you ultimately get the Stack Level Too Deep error). Change your do_foobar method to the following (you don't need the first two lines of your method, they're redundant, and you don't need to call update_attributes , as this is what's triggering the error):

after_update :do_foobar

def do_foobar
  self.rating = (rating_score/ratings)
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM