在保存之前在方法中使用pp(漂亮打印)允许我的模型成功保存,否则失败

时间:2014-08-01 00:17:12

标签: ruby-on-rails ruby ruby-on-rails-4 pretty-print

我有一个看起来像这样的对象:

它用于允许resumes的用户申请' (工作)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

每当我创建一个新的Jobapp对象时,作业总是失败。

如果我将default_values模型上的Jobapps方法更改为:

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

创建并保存对象。


控制台输出:

当我尝试拥有一个Resume对象apply_to一个Listing对象时,应创建一个Jobapp对象:

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)

pp self方法中有default_values行时:

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)

一些引用的方法:

以下是控制器的apply方法:

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

以下是Resume.apply_to方法:

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

说明:

它闻起来像是我用条件apply方法做了一些奇怪的事情(这很烦人),但我不认为这是失败的原因(如果失败的话,那就失败了我取出奇数条件并简化Resume.apply_to方法以简单地create对象,而不是使用new然后save

2 个答案:

答案 0 :(得分:1)

据我所知,这是因为self.denied = false返回false,因此你的回调返回false,这将取消所有未来的回调和相关操作:

  

如果before_ *回调返回false,则取消所有后续回调和相关操作。如果after_ *回调返回false,则取消所有后续回调。回调通常按照定义的顺序运行,但定义为模型上的方法的回调除外,这些回调最后被调用。

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

确保您的default_values方法返回true。

答案 1 :(得分:0)

来自ActiveRecord Callbacks documentation

  

如果before_ *回调返回false,则取消所有后续回调和相关操作。

在你的回调中你有:

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

因此,如果您记住所有块(包括块,方法,开始/结束块等)返回块中的最后一个值...那么您将从您的方式中有效地返回false打回来。那就是:

  1. self.denied = falseself.denied设为false,然后返回false
  2. 此周围的if块会返回块中的最后一个值,或false
  3. 该方法返回方法(块)中的最后一个值,或false
  4. 因此,您的回调会取消save操作。
  5. 此外,当您引入pp self语句时,那将有效地输出self,然后返回self,这不是false(显然)。

    因此,要修复非pp self版本,我建议您最后返回true,因为在评估了您的内容之后,您很可能不想中止save回调方法。在这里,使用惯用的||=运算符稍微简化了一下。

    def default_values
      self.denied ||= false
      true
    end
    

    以上||=的使用与:self.denied || self.denied = false相同。