I need to call create
on a model, and skip just one of the many Concerns that are included in that model definition.
after_create
callbacksModel
class Team < ApplicationRecord
include SomeConcernINeed
include SomeConcernIDontNeed
include AnotherConcernINeed
belongs_to :organization
...
# etc
Concern
module SomeConcernIDontNeed
extend ActiveSupport::Concern
included do
after_create :call_some_service
def call_some_service
::SomeServiceCallINeed.perform_later(self)
end
...
# etc
My code
Team.find_or_create_by!(name: "Foo") do |team|
# need to skip concern here
end
I'm not a rails developer, but a software tester. I am creating a rake task to seed a heroku review app for automation tests.
I am working with a large legacy codebase that I am not allowed, nor advised, to make any changes, because of how deeply coupled and nested the logic of the application is.
The rake task I am running creates records during the release phase of the heroku deployment, and many of the these models are dependent on other tables, or create dependent records on a perform_later
service call.
Because the workers are not up and running during the release phase, and I can't count on the dependent records I need later in the script to be created by the Concerns, so I call some of the services manually. E.g. A Team needs a User which needs an Application which has many Questions.
The problem is after the release phase, the server boots up, and the workers start processing all the delayed jobs that are enqueued by the 1000+ records I just seeded. This is fine for some jobs, as the services they call are idempotent. But one in particular creates 1300 duplicate records.
With the heroku-postgresql:hobby-dev plan that comes standard with all review apps, I am limited to 10k rows in the DB before write privileges are revoked. I need to limit the total number of rows in my DB, and this is the place where I can have the greatest impact.
I have not seen any other questions to address this specific need.
I know there is a way to skip callbacks
Team.skip_callbacks(:after_create)
But this will negate the other after_create
callbacks I still need (I think).I don't know if I can use a similar utility or line of code that will work for my situation.
I tried moving the rake task to the postdeploy
script in my app.json
config, but with the limited computing resources at my disposal, the delayed_job queue just falls over with the sheer volume it's hammered with all at once.
I tried to reduce my seeds, but I must mock up pre-existing data that an existing test suite is running against. I am not able to copy the DB to the review app because of its size.
Skipping an ActiveSupport:Concern callback is essentially no different than skipping a callback that is directly in the model. The concern name is of no importance, as according the code, this is all happening in one execution.
Therefore, you have access to the callback method directly, so simply skip the callback by name before creating the record.
Team.skip_callback(:create, :after, :call_some_service)
Team.create()
Make sure to clean up afterwards by setting the callback again so that future records still use the callback.
Team.set_callback(:create, :after, :call_some_service)