【问题标题】:What is this syntax inside ruby clases?ruby 类中的这种语法是什么?
【发布时间】:2016-01-21 11:09:13
【问题描述】:
class ApplicationController < ActionController::Base
  protect_from_forgery #What is this syntax? When is this executed and how to create one?
end

class Comment < ActiveRecord::Base
  belongs_to :post
  attr_accessible :body, :commenter, :post
end

在第一种情况下,我理解 ApplicationController 是模块 ActionController 中一个名为 Base 的新派生类。下一行会发生什么? protect_from_forgery 是基类中的方法还是模块 ActionController 中的方法?这叫什么?我在 ruby​​ 类文档中找不到。我尝试在基类中创建一个方法,但出现如下错误。如何创建可以在类中使用的特殊命令?

class Base
  def foo
    @name = "foo"
  end
end

class Der < Base
  foo
  def bar
    @dummy = "bar"
  end
end

错误:

expr1.rb:62:in `<class:Der>': undefined local variable or method `foo' for Der:Class (NameError)
    from expr1.rb:61:in `<main>'

【问题讨论】:

  • 这些是 rails 方法,而不是 ruby​​。这就是你找不到它们的原因。 forgery_protection。是ActionController中的类方法@
  • @japed 我如何创建这样的方法?什么时候执行?为什么我的示例不起作用?

标签: ruby-on-rails ruby


【解决方案1】:

它的继承。在您的子类中,您可以使用从父类继承的所有方法。 首先,您可以在类实例上调用方法。 在您的示例中,您可以这样做:

    base_object = Base.new
    base_object.foo

    der_object = Der.new
    der_object.bar

还要感谢继承,您可以这样做:

    der_object.foo

这里是 ruby​​ 继承的简单教程和示例: http://rubylearning.com/satishtalim/ruby_inheritance.html

编码愉快!

【讨论】:

【解决方案2】:

要创建类方法,您可以执行以下任一操作。

class Base
  def self.foo
  end
end

class Base
  class << self
    def foo
    end
  end
end

因为它们是你在类上调用它们的类方法

Base.foo

【讨论】:

    【解决方案3】:

    protect_from_forgery 是在 ActionController::Base 中包含的模块之一中定义的类方法,当您从 ActionController::Base 继承时可用于子类。

    Rails 中的这种方法有时被称为“宏”,因为它们是启用某些特定功能的类方法(有时还使用元编程来定义额外的方法或帮助程序)。实际上,术语“宏”是不正确的,因为 Ruby 没有宏。它们只不过是类方法。

    要记住的最重要的细节是,当它们在类定义中使用时。这些方法在代码评估时运行,而不是在运行时运行。

    class Base
      def foo_instance
        p "foo instance"
      end
    
      def self.foo_class
        p "foo class"
      end
    end
    
    class Der < Base
      foo_class
      def bar
        p "bar"
      end
    end
    
    Der.new.bar
    

    会产生

    "foo class"
    "bar"
    

    【讨论】:

      【解决方案4】:

      所以你说的是“类方法”——类方法是在类本身上定义的方法,而不是在类的实例上。请注意以下几点:

      class Greeter
        def initialize(name)
          @name = name
        end
      
        def greet
          "hello, #{@name}"
        end
      end
      
      Greeter.new("bob").greet # => "hello, bob"
      

      #greetGreeter 类的实例方法。然而,.new 是一个“类方法”——它是在类本身上调用的方法。尝试在 Greeter 类上调用 .greet 将导致 NameError

      Greeter.greet # ! NameError
      

      所以如果要定义这样的“类方法”,就必须使用以下语法之一:

      class Greeter
        def self.greet(name)
          "hello, #{name}"
        end
      
        class << self
          def greet(name)
            "hello, #{name}"
          end
        end
      
        class << Greeter
          # same as above
        end
      end
      
      def Greeter.greet(name)
        "hello, #{name}"
      end
      

      回到最初的问题,如果你重新打开greeter类,你现在可以使用.greet方法:

      class Greeter
        greet "bob" # => "hello, bob"
      end
      

      这也适用于子类化:

      class Host < Greeter
        greet "bob" # => "hello, bob"
      end
      

      这就是 Rails 提供这些方法的方式——它们在基类上定义类方法,最常见的是 ActiveRecord::Base,然后您可以使用它——解释诸如 protect_from_forgery 之类的方法。

      【讨论】:

        【解决方案5】:

        protect_from_forgery 是一个类方法:可能是这样的

         def protect_from_forgery(options = {})
                self.forgery_protection_strategy = protection_method_class(options[:with] || :null_session)
                self.request_forgery_protection_token ||= :authenticity_token
                prepend_before_action :verify_authenticity_token, options
                append_after_action :verify_same_origin_request
              end
        

        所以它被应用程序控制器继承:

        class ApplicationController < ActionController::Base
        

        你的例子可以这样写:

        class Base
          class << self
            def foo
              @name = "foo"
            end
          end
        end
        
        class Der < Base
          foo     #class method from Base
          def bar
            @dummy = "bar"
          end
        end
        

        查看 foo 的值

        Der.foo.inspect
        

        【讨论】:

          猜你喜欢
          • 2015-09-24
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多