无法理解ruby代码片段

时间:2017-12-01 16:31:20

标签: ruby-on-rails ruby

请原谅我的noob问题。我是ruby和rails的初学者,我在Rails中开发了一个向导或多步骤表单。我正在关注这篇文章

https://medium.com/@nicolasblanco/developing-a-wizard-or-multi-steps-forms-in-rails-d2f3b7c692ce

  module Wizard
    module User
      STEPS = %w(step1 step2 step3 step4).freeze

      class Base
        include ActiveModel::Model
        attr_accessor :user

        delegate *::User.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :user

        def initialize(user_attributes)
          @user = ::User.new(user_attributes)
        end
      end

      class Step1 < Base
        validates :email, presence: true, format: { with: /@/ }
      end

      class Step2 < Step1
        validates :first_name, presence: true
        validates :last_name, presence: true
      end

      class Step3 < Step2
        validates :address_1, presence: true
        validates :zip_code, presence: true
        validates :city, presence: true
        validates :country, presence: true
      end

      class Step4 < Step3
        validates :phone_number, presence: true
      end
    endmodule Wizard
    module User
      STEPS = %w(step1 step2 step3 step4).freeze

      class Base
        include ActiveModel::Model
        attr_accessor :user

        delegate *::User.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :user

        def initialize(user_attributes)
          @user = ::User.new(user_attributes)
        end
      end

      class Step1 < Base
        validates :email, presence: true, format: { with: /@/ }
      end

      class Step2 < Step1
        validates :first_name, presence: true
        validates :last_name, presence: true
      end

      class Step3 < Step2
        validates :address_1, presence: true
        validates :zip_code, presence: true
        validates :city, presence: true
        validates :country, presence: true
      end

      class Step4 < Step3
        validates :phone_number, presence: true
      end
    end
  end

1)以下代码段的作用是什么?

     delegate *::User.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :user

2)以下代码段的作用是什么?

    def initialize(user_attributes)
      @user = ::User.new(user_attributes)
    end

任何帮助都是高度赞赏的。谢谢!

1 个答案:

答案 0 :(得分:2)

问题#1

太宽泛了。所以,我会在那里通过。

问题2:这是做什么的?

delegate *::User.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :user

我将使用Person执行此操作,因为这就是我的应用中的(不是User)。

所以...... ::表示应该在全局命名空间中查找该类(称为Constant)。这表明该片段来自引擎(虽然,但不一定)。

::Person

.attribute_namesarray表生成persons个字段名称。

> ::Person.attribute_names

 => ["id", "first_name", "last_name", "date_of_birth", "created_at", "updated_at", "sex_id", "ethnicity_id"] 

.map{ |attr| [attr, "#{attr}="] }生成array arrays,其中每个array的内容将成为委托gettersetter

> ::Person.attribute_names.map{ |attr| [attr, "#{attr}="] }

 => [["id", "id="], ["first_name", "first_name="], ["last_name", "last_name="], ["date_of_birth", "date_of_birth="], ["created_at", "created_at="], ["updated_at", "updated_at="], ["sex_id", "sex_id="], ["ethnicity_id", "ethnicity_id="]] 

但是,我们需要array,而不是array arrays。所以,.flatten完成了这项工作。

> ::Person.attribute_names.map{ |attr| [attr, "#{attr}="] }.flatten

 => ["id", "id=", "first_name", "first_name=", "last_name", "last_name=", "date_of_birth", "date_of_birth=", "created_at", "created_at=", "updated_at", "updated_at=", "sex_id", "sex_id=", "ethnicity_id", "ethnicity_id="] 

借鉴this post

  

splat运算符(即*)将原本将数组转换为赋值列表

基本上,数组中的每个元素都将成为delegate的参数。

delegate告诉对象存在这行代码,将方法调用传递给另一个对象。

to: :user表示将方法调用传递到哪个对象。在这种情况下,:user是一个方法调用,可能包含::User的实例。

如果您手动执行此操作,它将类似于:

delegate  :id,
          :id=, 
          :first_name,
          :first_name=,
          ...,
          to: :person

问题3:这是做什么的?

def initialize(user_attributes)
  @user = ::User.new(user_attributes)
end

每个class constant都来自Class('root'class Constant):

> class Foo; end
  => nil

> Foo.is_a?(Class)
 => true 

每个class Constant都将initialize作为Class的私有方法继承:

> Class.private_methods.include?(:initialize)
 => true

initialize是您在new(例如class ConstantUser.new或其他)上致电Foo.new时调用的方法:

class Foo

private

  def initialize
    puts "initializing"
  end

end

> Foo.new
initializing
  => #<Foo:0x00000006fe5140>

initialize(继承自Class)不接受任何参数。

> Foo.new(:baz)
 ArgumentError: wrong number of arguments (given 1, expected 0)

但是,您可以在任何给定的类定义中覆盖它:

class Foo

  attr_accessor :bar

private

  def initialize(bar)
    puts "initializing"
    @bar = bar
  end

end

现在Foo将接受new的参数:

> @foo = Foo.new(:baz)
initializing
 => #<Foo:0x00000006f64720 @bar=:baz> 

> @foo.bar
 => :baz

这是怎么回事:

def initialize(user_attributes)

此行只是创建::User的新实例,并传递user_attributes,该实例已分配给实例变量@user

@user = ::User.new(user_attributes)