I have a simple url that will toggle one field in my search model. (locked) I want to toggle this field by clicking on a link.
example:
http://localhost:3000/search/toggle/fe5c72164908af20a7727f324e2fdbc1
The link works fine for one call then gives me the following error:
undefined method `locked' for nil:NilClass
the toggle p开发者_Go百科ath is just pointed to the searches update method:
route:
map.connect 'search/toggle/:id', :controller => 'searches', :action => 'update'
update action looks like:
def update
@search = Search.find_by_permalink(params[:id])
if @search.locked == 1 then
@search.locked = 0
else
@search.locked = 1
end
respond_to do |format|
if @search.update_attributes(params[:search])
flash[:notice] = 'Search was successfully updated.'
format.xml { head :ok }
format.js
else
format.html { redirect_to('/users/current') }
format.js
end
end
end
I also have a ajax call looks like:
$j('a.lock-status').live('click', function(e) {
$j.get($j(this).attr('href'));
e.preventDefault();
});
To summarize:
If I enter a toggle URL into the URL bar of the browser it works once. If I hit refresh it fails and gives me the above error.
If I use the ajax call it works once.
If I use the ajax call then refresh the page, it will work for that first request every time.
I have a feeling this might have something to do with GET/POST requests in rails but I'm not sure? I have narrowed it down to:
@search = Search.find_by_permalink(params[:id])
retuning nill on any call after the first one, but I'm not sure why its doing that?
UPDATE 1:
Here is the log output for 2 requests. (1st works, 2nd fails):
Processing SearchesController#update (for 127.0.0.1 at 2011-06-13 16:19:39) [GET]
Parameters: {"action"=>"update", "id"=>"9036304997196d83b20cba82a0cc67b8", "controller"=>"searches"}
Search Columns (1.0ms) SHOW FIELDS FROM `searches`
Search Load (0.4ms) SELECT * FROM `searches` WHERE (`searches`.`permalink` = '9036304997196d83b20cba82a0cc67b8') LIMIT 1
SQL (0.1ms) BEGIN
Search Update (0.2ms) UPDATE `searches` SET `locked` = 1, `updated_at` = '2011-06-13 23:19:39', `permalink` = '97894f26ba36761d04575260b132c230' WHERE `id` = 282
SQL (0.3ms) COMMIT
Rendering searches/update
Completed in 17ms (View: 6, DB: 2) | 200 OK [http://localhost/search/toggle/9036304997196d83b20cba82a0cc67b8]
SQL (0.1ms) SET NAMES 'utf8'
SQL (0.1ms) SET SQL_AUTO_IS_NULL=0
Processing SearchesController#update (for 127.0.0.1 at 2011-06-13 16:19:41) [GET]
Parameters: {"action"=>"update", "id"=>"9036304997196d83b20cba82a0cc67b8", "controller"=>"searches"}
Search Columns (1.0ms) SHOW FIELDS FROM `searches`
Search Load (0.4ms) SELECT * FROM `searches` WHERE (`searches`.`permalink` = '9036304997196d83b20cba82a0cc67b8') LIMIT 1
NoMethodError (undefined method `locked' for nil:NilClass):
app/controllers/searches_controller.rb:84:in `update'
/Users/Nick/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/webrick/httpserver.rb:104:in `service'
/Users/Nick/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/webrick/httpserver.rb:65:in `run'
/Users/Nick/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/webrick/server.rb:173:in `start_thread'
/Users/Nick/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/webrick/server.rb:162:in `start'
/Users/Nick/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/webrick/server.rb:162:in `start_thread'
/Users/Nick/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/webrick/server.rb:95:in `start'
/Users/Nick/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/webrick/server.rb:92:in `each'
/Users/Nick/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/webrick/server.rb:92:in `start'
/Users/Nick/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/webrick/server.rb:23:in `start'
/Users/Nick/.rvm/rubies/ruby-1.8.7-p334/lib/ruby/1.8/webrick/server.rb:82:in `start'
Rendered rescues/_trace (109.8ms)
Rendered rescues/_request_and_response (1.1ms)
Rendering rescues/layout (internal_server_error)
UPDATE 2:
OK, I see what you guys are saying... not sure what would be changing the permalink. I'm going to double check the model code in the AM.
Thanks!
As nowk said, your permalink doesn't appear to be a constant ID for entries in your Search table.
On the first request you update the permalink value and in the second request you try to find the entry using the old permalink value, which clearly doesn't exist any more.
Your controller should check for nil after this line : @search = Search.find_by_permalink(params[:id])
If you got a nil you should return back with a 404, because the specified record was not found.
In this case, however, if a new permalink on every update makes sense for your application, on a successful toggle you might want to send back the updated permalink and use that for subsequent requests.
(Ideally this should have been a comment to nowk's answer, but I could not find the comment box. Hence another answer)
Parameters: {"action"=>"update", "id"=>"9036304997196d83b20cba82a0cc67b8", "controller"=>"searches"}
Search Columns (1.0ms) SHOW FIELDS FROM `searches`
Search Load (0.4ms) SELECT * FROM `searches` WHERE (`searches`.`permalink` = '9036304997196d83b20cba82a0cc67b8') LIMIT 1
Search Update (0.2ms) UPDATE `searches` SET `locked` = 1, `updated_at` = '2011-06-13 23:19:39', `permalink` = '97894f26ba36761d04575260b132c230' WHERE `id` = 282
You sent in id 9036304997196d83b20cba82a0cc67b8
but your model is saving 97894f26ba36761d04575260b132c230
Why is your permalink
being updated by a different value? Is your permalink
setter regenerating on assignment?
If this is the case, would explain why you are getting nil
back on the 2nd identical id
request.
Try changing this:
if @search.update_attributes(params[:search])
to this:
if @search.save
精彩评论