Search code examples
ruby-on-railsrubyruby-on-rails-4pretty-print

Using pp (Pretty Print) in a method before save allows my model to save successfully, it fails otherwise


I have an object that looks like this:

It is used to allows users with resumes to 'apply to' (job)listings.

# == Schema Information
#
# Table name: jobapps
#
#  id         :integer          not null, primary key
#  denied     :boolean
#  listing_id :integer
#  resume_id  :integer
#  created_at :datetime
#  updated_at :datetime
#

class Jobapp < ActiveRecord::Base
  belongs_to :listing
  belongs_to :resume
  validates_uniqueness_of :listing_id, scope: :resume_id
  before_save :default_values

  . . .

private

  def default_values
    if self.denied.nil?
      self.denied = false
    end
  end
end

Whenever I create a new Jobapp object, the job always fails.

If I change the default_values method on the Jobapps model to:

def default_values
  if denied.nil?
    self.denied = false
    pp self
  end
end

The object is created and saved.


Console Output:

When I attempt to have a Resume object apply_to a Listing object, which should create a Jobapp object:

Started POST "/listings/1/apply?resume=8" for 127.0.0.1 at 2014-07-31 18:43:33 -0500
Processing by ListingsController#apply as HTML
  Parameters: {"authenticity_token"=>"htbHjaZnkqRMfgSUAQA5zOXB3ax/MAaHRUx8jRWr/lw=", "resume"=>"8", "id"=>"1"}
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
  Listing Load (0.2ms)  SELECT "listings".* FROM "listings" WHERE "listings"."id" = $1 LIMIT 1  [["id", "1"]]
   (0.2ms)  SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["user_id", 1]]
  Resume Load (0.2ms)  SELECT "resumes".* FROM "resumes" WHERE "resumes"."id" = $1 LIMIT 1  [["id", "8"]]
   (0.2ms)  BEGIN
  Jobapp Exists (0.2ms)  SELECT 1 AS one FROM "jobapps" WHERE ("jobapps"."listing_id" = 1 AND "jobapps"."resume_id" = 8) LIMIT 1
   (0.1ms)  ROLLBACK
Redirected to http://0.0.0.0:3000/listings/1
Completed 302 Found in 102ms (ActiveRecord: 1.5ms)

When I have the pp self line in the default_values method:

Started POST "/listings/1/apply?resume=8" for 127.0.0.1 at 2014-07-31 18:41:36 -0500
Processing by ListingsController#apply as HTML
  Parameters: {"authenticity_token"=>"htbHjaZnkqRMfgSUAQA5zOXB3ax/MAaHRUx8jRWr/lw=", "resume"=>"8", "id"=>"1"}
  User Load (1.0ms)  SELECT "users".* FROM "users" WHERE "users"."id" = 1 ORDER BY "users"."id" ASC LIMIT 1
  Listing Load (0.2ms)  SELECT "listings".* FROM "listings" WHERE "listings"."id" = $1 LIMIT 1  [["id", "1"]]
   (2.3ms)  SELECT COUNT(*) FROM "roles" INNER JOIN "users_roles" ON "roles"."id" = "users_roles"."role_id" WHERE "users_roles"."user_id" = $1 AND (((roles.name = 'admin') AND (roles.resource_type IS NULL) AND (roles.resource_id IS NULL)))  [["user_id", 1]]
  Resume Load (0.3ms)  SELECT "resumes".* FROM "resumes" WHERE "resumes"."id" = $1 LIMIT 1  [["id", "8"]]
   (0.1ms)  BEGIN
  Jobapp Exists (0.2ms)  SELECT 1 AS one FROM "jobapps" WHERE ("jobapps"."listing_id" = 1 AND "jobapps"."resume_id" = 8) LIMIT 1
"here it is"
#<Jobapp id: nil, denied: false, listing_id: 1, resume_id: 8, created_at: nil, updated_at: nil>
  SQL (0.3ms)  INSERT INTO "jobapps" ("created_at", "denied", "listing_id", "resume_id", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "id"  [["created_at", Thu, 31 Jul 2014 23:41:36 UTC +00:00], ["denied", false], ["listing_id", 1], ["resume_id", 8], ["updated_at", Thu, 31 Jul 2014 23:41:36 UTC +00:00]]
   (0.5ms)  COMMIT
Redirected to http://0.0.0.0:3000/listings/1
Completed 302 Found in 120ms (ActiveRecord: 4.9ms)

Some referenced methods:

Here is the apply method from the controller:

def apply
  set_resume
  if @resume.apply_to(@listing)
    redirect_to @listing
  else
    redirect_to @listing, alert: 'Unable to apply for job'
  end
end

Here is the Resume.apply_to method:

def apply_to(listing)
  jobapp = Jobapp.new(resume: self, listing: listing)
  jobapp.save
end

Notes:

It smells like I'm doing something weird with the conditional apply method (which is annoying) but I don't think that's the reason for the failure (it fails if I take out the odd conditional and simplify the Resume.apply_to method to simply create the object rather than using new then save.


Solution

  • From what I can tell, this is because self.denied = false returns false, and so your callback is returning false, which will cancel all future callbacks and associated action:

    If a before_* callback returns false, all the later callbacks and the associated action are cancelled. If an after_* callback returns false, all the later callbacks are cancelled. Callbacks are generally run in the order they are defined, with the exception of callbacks defined as methods on the model, which are called last.

    http://api.rubyonrails.org/v4.1.1/classes/ActiveRecord/Callbacks.html

    Just make sure your default_values method returns true.