“super”和“super do | u |”之间的区别使用Devise的上下文

时间:2015-05-24 18:30:18

标签: ruby-on-rails ruby ruby-on-rails-4 devise super

好的,所以我觉得我得到了超级does独立的东西。基本上在Devise中,如果Users::RegistrationsController < Devise::RegistrationsController,那么在任何操作上,拥有super将首先在父Devise::RegistrationsController中为同一个命名操作调用逻辑,然后调用你所写的内容

换句话说......

class Devise::RegistrationsController
  def new
    puts "this is in the parent controller"
  end
end

class Users::RegistrationsController < Devise::RegistrationsController
  def new
    super
    puts "this is in the child controller"
  end
end

# Output if users#new is run would be:
# => "this is in the parent controller"
# => "this is in the child controller"

# If super were reversed, and the code looked like this
# class Users::RegistrationsController < Devise::RegistrationsController
  #  def new
    #  puts "this is in the child controller"
    #  super
  #  end
#  end
# Then output if users#new is run would be:
# => "this is in the child controller"
# => "this is in the parent controller"

我很好奇的是,我看到有些人这样做了:

class Users::RegistrationsController < Devise::RegistrationsController
  def new
    super do |user|
      puts "something"
    end
  end
end

我很难绕过do block正在完成的事情。在我的例子中,在创建资源(用户)之后,我想在该资源(用户)上调用另一个方法。

当前代码:

class Users::RegistrationsController < Devise::RegistrationsController
  def new
    super do |user|
      user.charge_and_save_customer
      puts user.inspect
    end
  end
end

我只是想知道这与做的有什么不同:

class Users::RegistrationsController < Devise::RegistrationsController
  def new
    super
    resource.charge_and_save_customer
    puts resource.inspect
  end
end

如果它有用,我已在下面添加了父Devise::RegistrationsController代码:

def new
  build_resource({})
  set_minimum_password_length
  yield resource if block_given?
  respond_with self.resource
end

2 个答案:

答案 0 :(得分:15)

让我试着解释一下这里发生了什么:

class Users::RegistrationsController < Devise::RegistrationsController
  def new
    super do |user|
      user.charge_and_save_customer
      puts user.inspect
    end
  end
end

当您致电super时,您将返回到父new行动,因此以下代码将立即执行:

def new
  build_resource({})
  set_minimum_password_length
  yield resource if block_given?
  # respond_with self.resource
end

但是等等......这里是yield,所以它产生当前resource到块,你可以认为块就像一个方法,它需要一个参数(user ),这里resource(来自父)将是参数:

# Here resource is assigned to user
user.charge_and_save_customer
puts user.inspect

现在,由于块完全执行,它将再次开始执行super:

respond_with self.resource

答案 1 :(得分:0)

堆栈溢出霸主不会让我发表评论,因为我没有任何互联网积分,但这是对“如果没有 yield 语句,super 会没有用吗?”这个问题的答案。在 michaelrbock 答案的评论部分。

如果super调用的方法中没有yield语句(或者等价的),那么super do块中的代码就不会被执行。但是,ruby 不会警告您该块未在运行,因此可能会产生误导。