加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

ruby-on-rails – Ruby on Rails Monkey修补Gem的模型

发布时间:2020-12-17 04:00:24 所属栏目:百科 来源:网络整理
导读:这可能很愚蠢,但我要包含一个代表我项目所需模型的宝石.我想在其中一个模型Person中添加一个方法to_custom_string. 我试图这样做(遵循this示例): 配置/初始化/扩展/ person.rb 其中包含的内容如下: class Person ActiveRecord::Base def to_custom_string
这可能很愚蠢,但我要包含一个代表我项目所需模型的宝石.我想在其中一个模型Person中添加一个方法to_custom_string.

我试图这样做(遵循this示例):
配置/初始化/扩展/ person.rb

其中包含的内容如下:

class Person < ActiveRecord::Base
  def to_custom_string
    address.street.to_s
  end
end

gem中的Person类具有has_one:address关联.

我遇到的问题是这个补丁似乎覆盖了gem中的Person类,而不是修补它.令人抓狂的是,这种覆盖行为只能通过rake来体验(来自gem的Person类中声明的所有关联都会丢失).

我的佣金任务是这样的:

namespace :convert
  task :all_persons => :environment do
    Person.where(:param => value).includes(:address).find_in_batches(:batch_size => 2000) do |persons|
      persons.each do |person|
        puts person.to_custom_string
      end
    end
  end
end

调用bundle exec rake convert:all_persons给了我:

Association named 'address' was not found; perhaps you misspelled it?

但是将rake任务中的代码复制并粘贴到rails控制台中工作正常.

我目前的解决方案是将Person的代码从gem复制到我的app / models目录中,并在那里使用我的to_custom_string方法,我知道这是错误的.

有人可以解释为什么a)irb保留了我的人事协会,但是rake没有,和b)我怎么可以得到佣金合作?

谢谢!

解决方法

首先,我将创建一个Module并将其包含在Person中,而不是重新打开该类.所以它看起来像那样

module CustomString
    def to_custom_string
      address.street.to_s
    end
  end

  Person.send(:include,CustomString)

此外,似乎Person模型在运行初始化程序时尚不可用.如果仍然不起作用,您可能希望将它放在application.rb中.

config.railties_order = [ModelEngine::Engine,:main_app,:all]

我猜它在irb而不是rake中工作的原因是因为它们以不同的方式查找类. Irb(我相信你通过运行rails控制台运行)一次加载所有类,因此它从引擎加载类,然后它运行初始化程序,你已经定义了引擎中的类.我猜(虽然我不确定)Rake在开发模式下使用延迟加载常量.所以它不会在最开始时加载所有类,只有在找到未定义的常量时才会加载.然后它开始寻找可以定义该常量的文件.由于你在初始化程序中放置了一些Person,因此它不会查找引擎的模型,因为它看到Person已经具有Person定义.这就是为什么包含模块而不是重新打开课程可能会有所帮助 – >它强制它将从引擎中查找Person常量.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读