Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby on rails Rails 3.2.21和Ruby 2.2.0中断Time.zone.parse_Ruby On Rails_Ruby - Fatal编程技术网

Ruby on rails Rails 3.2.21和Ruby 2.2.0中断Time.zone.parse

Ruby on rails Rails 3.2.21和Ruby 2.2.0中断Time.zone.parse,ruby-on-rails,ruby,Ruby On Rails,Ruby,在Rails 3.2.21和Ruby 2.2.0p0中,时区解析器被破坏。在Ruby 2.1.2中,它运行得很好 [1] pry(main)> Time.zone.parse("2015-01-12") NoMethodError: undefined method `year' for nil:NilClass from /Users/user/.rvm/gems/ruby-2.2.0/gems/activesupport-3.2.21/lib/active_support/values

在Rails 3.2.21和Ruby 2.2.0p0中,时区解析器被破坏。在Ruby 2.1.2中,它运行得很好

[1] pry(main)> Time.zone.parse("2015-01-12")
NoMethodError: undefined method `year' for nil:NilClass
from /Users/user/.rvm/gems/ruby-2.2.0/gems/activesupport-3.2.21/lib/active_support/values/time_zone.rb:275:in `parse'

现在我知道你可以用
Time.parse(“2015-01-12”).localtime来代替它,但这会破坏我应用程序的功能。有任何已知的修复方法吗?

所以,这是您最初的情况:

class Dog

  def do_stuff(x, y=2)
     puts x + y
  end

end


d = Dog.new
d.do_stuff(1)

--output:--
3
但是,do_stuff()的代码已经更改,现在您面临类似的问题:

class Dog

  def do_stuff(x, y=nil)
     puts x + y
  end

end


d = Dog.new
d.do_stuff(1)


--output:--
1.rb:4:in `+': nil can't be coerced into Fixnum (TypeError)
    from 1.rb:4:in `do_stuff'
    from 1.rb:10:in `<main>'
根据rails文档,返回一个对象,因此该类定义了
parse()
,这是您想要别名的方法。因此,代码如下所示:

class Timezone  #Re-open the Timezone class.
  alias_method :orig_parse, :parse  #Create an additional name for parse().

  def parse(str, now=now())  #Now, redefine parse().
    orig_parse(str, now)     #Call the original parse() method.
  end
end
然后,您可以像往常一样调用parse():

Time.zone.parse("2015-01-12")
我想你应该把代码放在app/helpers/application\u helper.rb
中。看看这是否有效


我认为上面的代码将被视为一种
适配器模式
。尽管如此,因为这个插件已经适合了——它只是不能产生你想要的结果——它可能被认为是一个
装饰器模式。因此,现在您可以在简历上注明在rails代码中使用自定义适配器和/或装饰器模式

TLDR:rails bug已经修复,3.2分支上的第一个修复版本是3.2.22

Ruby 2.2更改了在名称不明确时解析默认参数的方式:

def now
  ...
end

def foo(now = now)
end
在较早版本的ruby中,调用
foo
而不使用参数会导致参数
now
被设置为
now()
方法调用的任何值。在ruby 2.2中,它将改为nil(并且您会得到一个关于循环引用的警告)

您可以通过执行以下任一操作来解决歧义:

def foo(now = now())
end

(显然,这一论点的用法正在改变)

显然,它过去的工作方式一直是一个bug。Rails有几个地方依赖这种不良行为,包括在AS::Timezone.parse中。该修复是针对3-2-stable分支的,并最终作为3.2.22的一部分发布

修复此问题的commit to rails有一个指向ruby bug的链接,该ruby bug是关于这个扩展答案的,因为在ActiveSupport::TimeZone类中定义了
parse
方法,所以您可以简单地打开它并相应地进行此微小更改

您可以将其放置在
config/initializers/timezone.rb下,或参考其他位置来调整此速度

class ActiveSupport::TimeZone
  alias_method :orig_parse, :parse  #Create an additional name for parse().

  def parse(str, now=now())  #Now, redefine parse().
    orig_parse(str, now)     #Call the original parse() method.
  end
end

复杂的问题:ruby 2.1.5和2.2甚至没有
Time.zone()
方法。有一个
zone()
实例方法,它的源代码在ruby 2.1.5和2.2之间发生了变化。不过,这是一些无法辨认的C代码。我不知道rails是否在其Time.zone()方法中使用了ruby的#zone方法。我在翻阅activesupport的源代码,似乎在2.1.2中使用的行
def parse(str,now=now)
现在在2.2.0中的右边
now
求值为零。在最新的activesupport主分支中,它现在更具体地被定义为
def parse(str,now=now())
,但这似乎是一个重大的突破性变化。好的,很好的侦查。请参阅我的答案,了解您可以做些什么。因为您描述了一个很好的解决方案,我认为在没有可用修复程序的情况下应该使用它(在本例中取消与稳定的3.2分支的链接)从Rails 3.2.22开始,commit现在已经发布:如果您使用的Rails版本不清楚是否已对其进行了后端口修复(在我的例子中是4.1),那么这是一个实用的解决方案。
def foo(something = now)
end
class ActiveSupport::TimeZone
  alias_method :orig_parse, :parse  #Create an additional name for parse().

  def parse(str, now=now())  #Now, redefine parse().
    orig_parse(str, now)     #Call the original parse() method.
  end
end