Ruby:类中实例变量的Singleton方法

时间:2017-09-21 07:04:16

标签: ruby-on-rails ruby attributes accessor singleton-methods

我正在接受ruby-kickstart(Josh Cheek)挑战,尽管我设法通过了所有测试,但有一件事我无法理解。

在练习中,您被要求覆盖<<实例变量的方法。具体来说,这就是你要做的事情:

  

在Ruby on Rails中,当一个人访问您网站上的网址时,   应用程序查看url,并将其映射到控制器方法   处理请求

     

我的老板希望能够指定CSS类的主体   HTML输出应该具有,基于哪种控制器方法   访问。我想提供一种方法,当被调用时,   将返回一个可以处理请求的字符串有几个   但是细微差别。您返回的字符串必须在保留期间保留   对象的整个生命方法必须能够被称为多个   times您返回的String应该知道如何添加新类:each   class由空格分隔您唯一需要担心的方法   被调用的是<<方法。    (加上一些其他不相关的东西)    示例:

controller = ApplicationController.new   
controller.body_class                  
#=> ""    
controller.body_class << 'admin'    
controller.body_class     
#=> "admin"   
controller.body_class << 'category'    
controller.body_class        
#=> "admin category"    
controller.body_class << 'page' << 'order'    
controller.body_class                  
#=> "admin category page order"

我的工作解决方案:

class ApplicationController 

  def initialize
    @body_class = ""
  end

  def body_class
    def @body_class.<<(str)
      puts "self is:"+self
      return self if self=~/\b#{Regexp.escape(str)}\b/
      if self==""
        self.concat(str)
      else
        self.concat(" ")
        self.concat(str)
      end
    end

    return @body_class
  end
end

一切都很完美。 但是我给出的早期解决方案(并没有起作用)是以下

class ApplicationController 
  attr_accessor :body_class
  def initialize
    @body_class = ""
  end

  def @body_class.<<(str)
    puts "self is:"+self
    return self if self=~/\b#{Regexp.escape(str)}\b/


    if self==""
      self.concat(str)
    else
      self.concat(" ")
      self.concat(str)
    end

  end

  def body_class                #Even this for the way I work it out on my mind is unnecessary 
    return @body_class
  end



end

当有人在第二个不工作的溶剂上运行以下

obj = ApplicationController.new
obj.body_class << "Hi"

&lt;&lt;方法不会被对象的单例覆盖。 我不明白为什么我必须在body_class方法中包装单例方法。 (请注意,在第二个解决方案中有一个attr_accessor。

是的,请有人赐教! 谢谢!

2 个答案:

答案 0 :(得分:4)

  

我不明白为什么我必须在body_class方法中包装单例方法。

访问正确的实例变量。当您尝试在方法之外覆盖它时,您将进入类上下文。此代码在类加载时运行。尚未创建任何实例。 (即使此时确实存在实例,@body_class实例变量也属于类ApplicationController,它本身就是类Class的实例。)

您需要实例上下文。

此外,我很确定这个问题可以在没有任何方法修补巫毒的情况下解决。只需提供一个不同的对象(符合相同的API。这称为&#34;鸭子打字&#34;)。

class ApplicationController

  def body_class
    @body_class ||= CompositeClass.new
  end

  class CompositeClass
    def initialize
      @classes = []
    end

    def <<(new_class)
      @classes << new_class
    end

    # I imagine, this is what is ultimately called on ApplicationController#body_class,
    # when it's time to render the class in the html.
    def to_s
      @classes.join(' ')
    end
  end
end

当然没有测试这段代码。

答案 1 :(得分:1)

BTW,正确的方法是明确use Symfony\Component\HttpFoundation\Session\Session; //setting up new session $session = new Session(); $session->start(); // set session attributes $session->set('name', 'Drak'); // get session attributes $session->get('name'); 实例变量:

extend