Разница между "супер" и "супер do | u |" используя контекст

Хорошо, поэтому я думаю, что я получаю, что супер 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

Ответ 1

Позвольте мне попытаться объяснить, что здесь происходит:

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

Теперь, поскольку блок выполнен полностью, он снова начнет выполнять супер:

respond_with self.resource