在同一模块中访问Ruby模块的方法

时间:2016-03-02 12:15:06

标签: ruby-on-rails ruby

我是Ruby新手,可能不懂基本的东西:

我正在尝试这个:

# lib/common_stuff.rb
module CommonStuff
  def self.common_thing
    # code
    @x = second_thing # --> should access method in same module. Doesn't work.
  end
  def self.second_thing
    # code
  end
end

# app/controllers/my_controller.rb
require 'common_stuff'
class MyController < ApplicationController
  include CommonStuff
  y = self.common_thing # accesses the Module method -> works
end

错误:

  

NoMethodError(未定义的方法`second_thing'for   MyController:0x000000088d8990):lib / common.rb:7:'common_thing'

我尝试了Module和实例方法。同样在Module中声明second_thing一个实例方法或两个方法作为实例方法都不起作用。我有什么误解?

**编辑更正**

我意识到我的错误是使方法类方法(使用self。前缀)。没有它它实际上是有效的。以为我试过了,但我一定是昨天失明了。所以工作代码是(只是一个构造的例子 - 通常我当然不会实例化控制器):

# lib/common_stuff.rb

module CommonStuff
  def common_thing
    @x = second_thing # -->  access method in same module.  Works now too. 
  end

  def second_thing
    10
  end
end

# app/controllers/my_controller.rb


require 'common_stuff.rb'

class MyController

  include CommonStuff

  def a_class
    y = common_thing # accesses the Module method -> works
    puts y
  end
end

ctrl = MyController.new
ctrl.a_class

1 个答案:

答案 0 :(得分:-1)

  

我误解了什么?

1)@variable是私有的,因此您始终需要提供访问方法来访问它(或使用instance_variable_get()来侵犯隐私权):

module CommonStuff
  def common_thing
    @x = second_thing # --> should access method in same module. Doesn't work.
  end

  def second_thing
    10
  end
end


class MyController 
  include CommonStuff

  attr_accessor :x
end

obj = MyController.new
obj.common_thing
puts obj.x

--output:--
10

2)您不能包含模块的类方法:

module CommonStuff
  def self.common_thing
    puts 'hello'
    @x = second_thing # --> should access method in same module. Doesn't work.
  end

  def self.second_thing
    10
  end
end

class MyController 
  include CommonStuff
end


CommonStuff.common_thing
MyController.common_thing

--output:--
hello

1.rb:21:in `<main>': undefined method `common_thing' for MyController:Class (NoMethodError)

#obj = MyController.new  
#obj.common_thing   #Same error here

如果要将一些类方法注入MyController,则需要重新编写CommonStuff模块:

module CommonStuff
  def self.included(includer)  #Advanced 'hook' method
    includer.extend ClassMethods
  end

  module ClassMethods
    def common_thing
      puts 'hello'
      @x = second_thing # --> should access method in same module. Doesn't work.
    end

    def second_thing
      10
    end
  end
end

class MyController 
  include CommonStuff
  y = common_thing
  puts y

  puts instance_variable_get(:@x)
end

--output:--
10
10

每当模块被另一个类/模块包含时,都会调用hook方法,并将该方法作为参数传递给包含类/模块。

对通讯的回应:

只有控制器的实例变量才能在视图中使用,例如:

class MyController

   def do_stuff
     @x = 10  #instance variable
   end

end

但在类方法中创建的@variables不是控制器的实例变量:

class MyController

   def self.do_stuff
     @x = 10  
   end

end

因此,在类方法中创建的@variables将无法在视图中使用。