小编Ben*_*t B的帖子

Rails 4.2自动加载不是线程安全的

我有以下型号:

class User < ActiveRecord::Base
  def send_message(content)
    MessagePoro.new(content).deliver!
  end

  def self.send_to_all(content)
    threads = []
    all.each do |user|
      threads << Thread.new do
        user.send_message(content)
      end
    end
    threads.each(&:join)
  end
end
Run Code Online (Sandbox Code Playgroud)

MessagePoro模型可以很简单,例如app/models/message_poro.rb:

class MessagePoro
  def initialize(content)
    # ...
  end

  def deliver!
    # ...
  end
end
Run Code Online (Sandbox Code Playgroud)

现在,当我有100个用户,并且我正在运行User.send_to_all("test")时,我有时会遇到更严重的错误:

RuntimeError: Circular dependency detected while autoloading constant MessagePoro
Run Code Online (Sandbox Code Playgroud)

要么:

wrong number of arguments (1 for 0)
Run Code Online (Sandbox Code Playgroud)

我认为它必须是因为没有加载MessagePoro并且所有线程都试图同时加载它,或类似的东西.由于这些错误有时只会发生,我很确定只有当存在"竞争条件"或者有线程时才会出现这种情况.我已经尝试在启动Threads之前初始化MessagePoro,并且我已经使用了eager_loading,但问题似乎仍然存在.还有什么可以尝试缓解这个问题?

multithreading eager-loading ruby-on-rails-4

9
推荐指数
2
解决办法
2956
查看次数

如何在Rails4引擎中添加autoload_path?

通常我在config/application.rb中添加以下内容来添加autload_paths:

config.autoload_paths += Dir[Rails.root.join('app', 'poros', '{**}')]
Run Code Online (Sandbox Code Playgroud)

如何在引擎中实现相同的目标?它似乎在我在主机应用程序中的application.rb中使用相同的代码时工作,但是我认为代码不在引擎中并且需要添加到主机应用程序以使事情有效是很难看的.

我发现通过引擎添加加载路径的唯一解决方案是将其添加到lib/engine/engine.rb:

config.to_prepare do
  Dir.glob(Rails.root + "../../app/poros/**/*.rb").each do |c|
    require_dependency(c)
  end
end
Run Code Online (Sandbox Code Playgroud)

然而,这似乎有一些根本性的错误,因为这会在我进行控制台重新加载时导致问题(例如,它告诉我已经定义了常量或者关注点无法执行包含块两次)

在引擎本身中执行此操作的正确方法是什么?(不敢相信这是如此艰难/不常见,我真的google了很多,但我找不到解决方案)

ruby-on-rails

5
推荐指数
1
解决办法
2906
查看次数

HUGE String上的Ruby String操作

我有一个大小约10 GB的字符串(大量的RAM使用...).问题是,我需要执行像gsub和split这样的字符串操作.我注意到Ruby会在某个时刻"停止工作"(尽管没有产生任何错误).

例:

str = HUGE_STRING_10_GB

# I will try to split the string using .split:
str.split("\r\n")
# but Ruby will instead just return an array with 
# the full unsplitted string itself...

# let's break this down:
# each of those attempts doesn't cause problems and 
# returns arrays with thousands or even millions of items (lines)
str[0..999].split("\r\n")
str[0..999_999].split("\r\n")
str[0..999_999_999].split("\r\n")

# starting from here, problems will occur
str[0..1_999_999_999].split("\r\n")
Run Code Online (Sandbox Code Playgroud)

我正在使用Ruby MRI 1.8.7,这里有什么问题?为什么Ruby无法对巨大的字符串执行字符串操作?什么是解决方案?

我想出的唯一解决方案是使用[0..9],[10..19],"循环"字符串,并逐个执行字符串操作.然而,这似乎是不可靠的,例如,如果我的拆分分隔符非常长并且落在两个"部分"之间.

实际上工作正常的另一个解决方案是像str.each_line {..}一样迭代字符串.但是,这只是替换了换行符分隔符.

编辑:谢谢你的所有答案.就我而言,"巨大的10 GB STRING"实际上是从互联网上下载的.它包含由特定序列分隔的数据(在大多数情况下是简单的换行符).在我的场景中,我将10 GB文件的EACH ELEMENT与我脚本中已有的另一个(较小的)数据集进行比较.我感谢所有的建议.

ruby memory string

3
推荐指数
1
解决办法
1754
查看次数

当Array已经是Enumerable时,为什么要使用Array#to_enum?

据我所知,Array类已经混合在Enumerable模块中.

如果是这样,为什么不存在[:example].next呢?

我为什么需要制作它[:example].to_enum.next

ruby arrays

3
推荐指数
1
解决办法
1413
查看次数

将UTF-8字符转换为正确的ASCII字符

我有字符串"V\355ctor"(我认为是Víctor).有没有办法将其转换为ASCII,í将被ASCII替换i

我已经尝试过没有成功的Iconv.(我只是得到了Iconv::IllegalSequence: "\355ctor")

此外,Ruby 1.8.7和Ruby 2.0之间存在差异吗?

编辑: Iconv.iconv('UTF-8//IGNORE', 'UTF-8', "V\355ctor")这似乎工作,但结果Vctor不是Victor

ruby ascii

2
推荐指数
1
解决办法
1227
查看次数