Do Fixtures Trigger Model Callbacks

Do fixtures trigger model callbacks?


Is this how it is expected to work? If
so, why did they design it this way?

Yes, fixtures do not use callbacks. I'm assuming this is for performance reasons. It is quicker to load the data straight into the database without instantiating the model.

Is there a way to force the triggering
of the callbacks when loading
fixtures?

Not that I know of. You have a couple options. One is to build your fixtures as if the callbacks were already triggered. That is, manually create the data that the callbacks would. For example, if you have a callback which hashes a user's password you would need to hash the password manually and then store that hash in the fixture.

The second solution (and highly recommended!) is to use factories. Factories do trigger callbacks and allow you to use virtual attributes, etc. This is because they do instantiate the model each time. One popular gem is Factory Girl. Another one to try is Machinist. I have also created a Railscasts episode on the topic.

Incorrect association in fixtures

I think it has to be with the id attribute in the repos fixture.
I'm using yml fixtures. I added the issue and the repo to the existing ones in the project.

issues.yml

issue_triage_sandbox:
user_name: bemurphy
name: issue_triage_sandbox
full_name: bemurphy/issue_triage_sandbox
language: ruby
created_at: 2012-11-10 21:50:48.351554000 Z
updated_at: 2012-11-10 21:50:48.351554000 Z
issues_count: 1

repos.yml

issue_triage_sandbox:
user_name: bemurphy
name: issue_triage_sandbox
full_name: bemurphy/issue_triage_sandbox
language: ruby
created_at: 2012-11-10 21:50:48.351554000 Z
updated_at: 2012-11-10 21:50:48.351554000 Z
issues_count: 1

From the console:

rake db:fixtures:load RAILS_ENV=test
rails c test

irb(main):001:0> i = Issue.last

=> #https://api.github.com/repos/bemurphy/issue_triage...", repo_name: nil, user_name: nil, last_touched_at: "2012-11-10 22:20:24", number: 1, created_at: "2012-11-10 23:23:45", updated_at: "2012-11-10 23:23:45", repo_id: 915227508, title: "first test issue in sinatra", html_url: "https://github.com/sinatra/sinatra/issues/1", state: "open", pr_attached: false>

irb(main):002:0> i.repo

Rails does not fire my after_commit callback

David mentioned the explanation for this behavior in the questions comment.

Transaction Callbacks documentation

"If any exceptions are raised within one of these callbacks, they will
be ignored so that they don't interfere with the other callbacks. As
such, if your callback code could raise an exception, you'll need to
rescue it and handle it appropriately within the callback."

see also:

  • Rails Github Issue 3205
  • Pull request #11123

Rake fixtures not populating correctly

The issue was as follows: The name of the model object that failed was pluralized, "MyTables" instead of "MyTable". Fixtures.rb makes a call to constantize to find the name of the class, which ordinarily raises a NameError exception when it fails, but in a fixture the exception is swallowed. The pluralized model object raised the exception and so the fixture was unable to determine what class it was trying to create. Without that information it didn't try to add timestamps to the insert statement - or labels or primary keys for that matter - and thus the error was thrown.

I imagine the error message would have been different if the code had been in a slightly different order. Maybe that was the difference between running on Linux and running on Windows.

Multiple after_update callbacks with attribute change conditions are triggering only the first one

You can just use one callback with an if...end block to filter operations you want to perform in each cases.

class Article < ActiveRecord::Base
after_update :method_1, :if => proc{ |obj| obj.status_changed? && obj.status == 'PUBLISHED' }
...

def method_1
if self.name == 'TEST'
# stuff you want to do on method_2
else
# stuff you want to do on method_1
end
end
end

Is there any easy way to trigger same instance method after different custom callbacks in Rails?

I don't understand why you would ever want to do this, but remember you can use Ruby code anywhere in your class definition.

callbacks = [:after_save, :after_update, :before_save, :before_create, after_commit]
callbacks.each do |callback|
self.send(callback, :simple_testing)
end

I've not tried this but it should work i think.



Related Topics



Leave a reply



Submit