views:

29

answers:

1

I'm trying to figure out an inconsistency between what's happening in a functional test and what is happening in my development environment. I have a custom validation method unique_entry that is essentially a specialized version of validates_uniqueness_of. It looks like this:

def unique_entry
  matched_entry = Entry.first(:conditions => ['LOWER(field_one) = LOWER(?) AND LOWER(field_two) = LOWER(?)', self.field_one, self.field_two])
  errors.add_to_base('Duplicate detected') if matched_entry && (matched_entry.id != self.id)
end

The update action in the controller is very basic:

def update
  if @entry.update_attributes(params[:entry])
    flash.now[:success] = 'Success'
    render :action => 'show'
  else
    flash.now[:error] = 'Error'
    render :action => 'edit'
  end
end

This works just fine when I'm creating a new record. When I update a record, however, I get inconsistent behavior. If I test it from a browser in my development environment, it correctly renders the edit action with an error message, but in my functional test, it accepts the update as successful. Here is the test:

test "should not update entry and should render edit view if invalid update" do
  put :update, { :id => 1, :field_one => 'new_value', :field_two => 'new_value' } # 'new values' are the same as another existing record to trigger the duplication check
  assert_template :edit
  assert_not_nil flash[:error]
end

I looked at the test log and discovered that the values unique_entry is using are the record's original values instead of the values it should be attempting to update with. That is, the first line of unique_entry generates an SQL query like this:

SELECT * FROM "entries" WHERE (LOWER(field_one) = LOWER('original_value_of_field_one') AND LOWER(field_two) = LOWER('original_value_of_field_two')) LIMIT 1

What am I missing here? Why do my validations seem to be running against the original record instead of the new values only in the test environment?

+2  A: 

In your test, shouldn't there be some reference to :entry, since that is what you are looking for in the controller params[:entry] ?

JRL
That was it! I had to change the test to use this line: `put :update, { :id => 1, :entry => { :field_one => 'new_value', :field_two => 'new_value' } }`. Thank you!
Jimmy Cuadra