views:

826

answers:

3

I want to set my summary field to a sanitized version of the body field, but only if the user does not supply their own summary ie. params[:document][:summary] is blank.

This appears to work fine if I create a new record, if I enter a summary it is saved, if I don't the body is used to generate the summary.

However when I update the record the summary always gets overridden. From my log files I can see that 'generate_summary' gets called twice, the second time the 'changes' hash is empty.

class Document << ActiveRecord::Base
  # Callbacks
  before_save  :generate_summary

private

  def generate_summary
    @counter ||= 1

    logger.debug '$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$'
    logger.debug @counter.to_s
    logger.debug 'changes: ' + self.changes.inspect
    self.summary = Sanitize.clean(self.body).to(255) if self.body && (!self.summary_changed? or self.summary.blank?)
    @counter = @counter + 1
end

Log on Update:

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

1

changes: {"summary"=>["asdasdasdasd", "three.co.uk"]}

Page Update (0.7ms) UPDATE documents SET meta_description = 'three.co.uk', summary = 'three.co.uk', updated_at = '2009-09-30 11:37:08' WHERE id = 77

SQL (0.6ms) COMMIT

SQL (0.1ms) BEGIN

$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$

2

changes: {}

Page Update (0.5ms) UPDATE documents SET meta_description = 'asdasdasdasd', summary = 'asdasdasdasd', updated_at = '2009-09-30 11:37:08' WHERE id = 77

A: 

Only logical explanation is that the controller somehow saves twice. Is this log from the console where you call update on the record or is it from a real request that comes through the controller?

nasmorn
A: 

Your controller probably saves twice as said by @nasmorn. You can also check that your body as changed before updating your summary.

if self.body_changed? && (!self.summary_changed? or self.summary.blank?)
  self.summary = Sanitize.clean(self.body).to(255)
end
Vincent
A: 

It seems 'update_attributes' triggers the before_save callback, so in my controller 'generate_summary' is called twice once by 'update_attributes' and once by 'save'. This is not expected behaviour.

Checking the body has changed as suggested by @vincent seems to prevent the unexpected behaviour.

Kris
Actually it is expected behavior - ActiveRecord follows a strict callback chain when saving to the database and update_attributes explicitly calls save as part of its process. If you merely want to set attributes without saving, use attributes=
latortuga
Thank you for pointing this out!
Kris