Sword 1.0b5 · A simple and friendly weblogging tool for academic environments created by Fingertips design & development.

 
 
 
 
 

Hanging FCGI-processes with Edge Rails and lighttp

TrackBack link: http://blog.markjuh.net/markjuh/trackback/2005/9/26/hanging_fcgi_processes_with_edge_rails_a

Published on 26 September 2005 at 14:51, updated at 14:51.

In category Rails.

For quite some time now, if you use lighttpd combined with Edge Rails, the Rails FCGI-processes don’t terminate when lighttpd terminates. This is strange, since lighttpd sends the TERM signal to the FCGI-processes. I had to use a kill -9 to actually end the FCGI-processes.

Rick Olson confirmed this behaviour and we tried to track it down. We couldn’t find it back then, but since then I got SO annoyed that I looked into it a bit more.

It seems that the problem is in vendor/rails/railties/lib/fcgi_handler.rb. It shows that the TERM signal is handled by the graceful_exit_handler. This handler sets whenready to :exit, which should make sure that the FCGI-process ends after processing the current or next FCGI-request.

And now this last part exactly forms the problem. When lighttpd terminates, the FCGI-process is waiting for the next request to come so it can finish gracefully. But the next request never comes, since lighttpd is already down, so there is no process to send requests to the FCGI-process.

So, I’ve written a dirty hack to fix this problem. David Heinemeier Hansson already promised to fix it the right way, but I just couldn’t wait for that to happen. (Using kill -9 every time you restart the webserver is just too annoying.)

Unexpected characters when using Prototype (AJAX)

TrackBack link: http://blog.markjuh.net/markjuh/trackback/2005/9/26/unexpected_characters_when_using_prototy

Published on 26 September 2005 at 13:27, updated on 2 October 2005 at 03:41.

In category Rails.

A little while back someone pointed me at the weird behaviour of my preview box when adding a comment. Somehow &_= was added to the end of the preview content.

It took me quite some time to figure out where it was coming from. I searched and searched, but couldn’t find the problem. I thought it wouldn’t be a Prototype bug, since Rails had been updated, but Prototype hadn’t changed.

So I asked around in #rubyonrails and Thomas Fuchs pointed me in the right direction.

It seemed changeset 2106 in Rails changed the way a Safari bug was tackled. It had been the case that Prototype added the &_= to the end of the POST data and ActionPack would strip this away again. But since another fix was found for this problem, there was no need for the &_= anymore.

So the following (line 213, or in the latest Edge Rails version line 476) should be removed from prototype.js:

if (parameters.length > 0) parameters += '&_=';

I had already discovered that removing the line fixed the problem, but it was good to find the reason why. And I’ve filed it as ticket 2258.

How to make sure an attribute doesn't get updated

TrackBack link: http://blog.markjuh.net/markjuh/trackback/2005/8/8/how_to_make_sure_an_attribute_doesn_t_ge

Published on 8 August 2005 at 10:55, updated at 20:53.

In category Rails.

I have a Rails model in which I don’t want the title attribute to change. I implemented this with a before_update:

  before_update :check_title_unchanged

  protected

  def check_title_unchanged
    Post.find(id).title == title
  end

This didn’t quite work because of an ActiveRecord bug I wrote about before.

When talking to Michael Koziarski at #rubyonrails about this bug, he made clear that I have at least one problem with my code and that I could have made a different implementation.

First to tackle the real problem in my code. The problem with my implementation is that it isn’t thread-safe, because the title could have been changed by another thread after we’ve fetched the object from the database. And hence our title wouldn’t have changed, but we still wouldn’t be able to save our model.

So the better way of doing it is by adding an after_find which is documented at the Rails Wiki. And also updating the before_update method accordingly.

  before_update :check_title_unchanged

  attr_accessor :original_title

  protected

  def after_find
    @original_title = title
  end

  def check_title_unchanged
    @original_title == title
  end

Now to take a look at another approach to tackle this. We could also override the validate method. The validate method has the following documentation:

Overwrite this method for validation checks on all saves and use Errors.add(field, msg) for invalid attributes.

So we could now change our code to:

  attr_accessor :original_title

  protected

  def after_find
    @original_title = title
  end

  def validate
    @original_title==title
  end

And if we would want to make it really nice, we would use Errors.add to add a descriptive error message, which is then added to the list of errors that will be displayed by error_messages_for. This would be the only reason I would use this approach instead of using a before_update.

So we could do:

  def validate
    result = (@original_title==title)

    if !result
      Errors.add(:title, "Title cannot be changed.")
    end
  end

Conclusion: in my project I have no use for the error message, so I don’t really see the point in overriding the validate method. But now I at least know the available options and can choose one wisely. So if I just need to make sure the title cannot be updated by a programming mistake in a controller, I use the before_update. If the user needs to be presented with a nice error message why they cannot change the title, then I would choose for overriding the validate method.

Update: I tried to put this nice piece of code to work, but it breaks my CRUD tests. My CRUD tests might behave a little different from the actual application, but still, they shouldn’t break. I actually create an object, save it, update it and then save it again. This failed, because I did not do a find for the same object and hence original_title is not yet set. So I’ll leave my implementation as it is currently. The issue with thread-safety is not that shocking in my case, since the title really shouldn’t be changed anyway.

Rails ActiveRecord bug

TrackBack link: http://blog.markjuh.net/markjuh/trackback/2005/7/29/rails_activerecord_bug

Published on 29 July 2005 at 16:43, updated at 16:48.

In category Rails.

Today I had to make sure a model couldn’t be saved if someone tried to update a certain field.

Reading in the API documentation I found the following:

If a before_* callback returns false, all the later callbacks and the associated action are cancelled.

So a before_update callback in my model would be the solution. I just had to make sure it would return false in the right cases.

Because of the last three months of test-driven development, I decided to write a test first. And to my surprise I could always save the model, even if my before_update callback would always return false. First I double-checked my test, but it was okay. Time to use yet another great tool in Rails: script/console.

It showed that even though the save method always returned true, it in fact did not save the model. So fortunately no problem with the before_update callback. This meant that there was no way avoiding it anymore… I would take my first dive into the ActiveRecord code.

After quite some time of searching back and forth through a couple of Ruby files, I found the problem:


def create_or_update
  if new_record? then create else update end
  true
end

And see here, it always returns true instead of the actual result from create or update. Why? Well, probably because there would be a problem in the create method:


def create
  self.id = connection.insert(
    "INSERT INTO #{self.class.table_name} " +
    "(#{quoted_column_names.join(', ')}) " +
    "VALUES(#{attributes_with_quotes.values.join(', ')})",
    "#{self.class.name} Create",
    self.class.primary_key, self.id, self.class.sequence_name
  )     

  @new_record = false 
end   

This create method returns the value of new_record (which is false), instead of the result of the query (self.id).

I’ve written a simple patch (see ticket #1861), which solves my problems and doesn’t introduce any new problems in my application. But again, it would be good to have a test for ActiveRecord. The problem is that I’m just not well-acquainted with ActiveRecord, so I have no idea where or how to incorporate the test. Any help with this would be greatly appreciated.