如何在 rails 模型中调用可重用代码?

How to call reusable code in rails model?

我的模型中有一个重复的方法,我想将这些代码放在一个地方,只是想将它访问到我的模型中。

我的模型有几个方法,例如:

class ProductionProductivity7 < ApplicationRecord
def self.import1(file)
  spreadsheet = Roo::Spreadsheet.open(file.path)
        header = spreadsheet.row(1)
        (2..spreadsheet.last_row).each do |i|
          row = Hash[[header, spreadsheet.row(i)].transpose]
          puts row.to_hash
          product = find_by(id: row["id"]) || new
          product.attributes = row.to_hash
          product.save!
    end
end
def self.search(search,compare)
  if search == "All"
    all.order(:id)
  elsif compare == "Bihar vs District"
    where("Districts = ? OR Districts = ?", search, "Bihar")
  else
    where(Districts: search)
  end
end

结束

还有 3 个这样的方法,我想把这个代码块放到 helper 中,只想在模型中调用它。为此,我尝试将这些代码放入我的助手中。我使用以下方式调用它:

include ApplicationController.ProductionProductivity7sHelper

我将其包含在我的模型中,但出现此错误:

undefined method `ProductionProductivity7sHelper' for ApplicationController:Class

我的控制器代码是这样的:

 def test
      @ProductionProductivity7s = ProductionProductivity7.search(params[:search],compare)
      a = ProductionProductivity7.query(@ProductionProductivity7s,params[:year],rain_fall_type,views,compare)
 end 

我在应用程序文件夹中添加了一个模块名称code.rb。

   module Code
    def search(search_scope,compare)
        if search_scope == "All"
        all.order(:id)
        elsif compare == "Bihar vs District"
        where("Districts = ? OR Districts = ?", search_scope, "Bihar")
        else
        where(Districts: search_scope)
        end
    end
end

我只想将我的模型的所有方法都写在某个地方,它可以是模块或帮助程序,而无需更改任何内容。有没有可能我只想在我的模型中使用这个代码块。

我正在要点文件中添加整个控制器代码和模型代码。请看一下 My controller and Model code link

我收到这个错误:

 undefined method `search' for #<Class:0x00007ff115974fd8> Did you mean? search1

如何制作一个像这样的模块:

module Import1

  def import1(file)
    spreadsheet = Roo::Spreadsheet.open(file.path)
    header = spreadsheet.row(1)
    (2..spreadsheet.last_row).each do |i|
      row = Hash[[header, spreadsheet.row(i)].transpose]
      puts row.to_hash
      product = find_by(id: row["id"]) || new
      product.attributes = row.to_hash
      product.save!
    end
  end

  def search(search_scope,compare)
    if search_scope == "All"
      all.order(:id)
    elsif compare == "Bihar vs District"
      where("Districts = ? OR Districts = ?", search_scope, "Bihar")
    else
      where(Districts: search_scope)
    end
  end

end

我想我会把它放在您的 app 文件夹中的某个地方,这样您就不会遇到自动加载问题。您 可以 将它放在您的根 app 文件夹中,但这对我来说似乎很乱。您 也可以 将它放在您的 models 文件夹中,但是您在同一个文件夹中有两种截然不同的东西,这对我来说也很乱。我想我会想创建一个新文件夹,例如 app/model_modulesapp/shared_model_modules,然后将您的 import_1.rb 文件放在那里。那么,这个文件是什么就一目了然了。

然后做:

class ProductionProductivity7 < ApplicationRecord
  extend Import1
end

或者,使用服务而不是助手怎么样? IMO,它使正在发生的事情变得更加明确,而助手可以混淆代码所在的位置。

基本结构 BaseService 可能看起来像:

class BaseService

  attr_accessor :args

  class << self

    def call(args=nil)
      new(args).call
    end

  end # Class Methods

  #=======================================================================
  # Instance Methods
  #=======================================================================

    def initialize(args)
      @args = args || {}
      assign_args
    end

  private

    def assign_args
      args.each do |k,v|
        class_eval do 
          attr_accessor k
        end
        send("#{k}=",v)
      end
    end

end

那么,您的文件导入服务可能类似于:

class ImportFileService < BaseService

  def call
    spreadsheet = Roo::Spreadsheet.open(file.path)
    header = spreadsheet.row(1)
    (2..spreadsheet.last_row).each do |i|
      row = Hash[[header, spreadsheet.row(i)].transpose]
      puts row.to_hash
      product = klass.find_or_initialize_by(id: row["id"])
      product.attributes = row.to_hash
      product.save!
    end
  end

end

你会这样称呼你的服务:

ImportFileService.call(file: file, klass: ProductionProductivity7)

当然可以,您可以像这样创建一个模块吗:

module ProductionProductivity7sHelper
  def import1(file) # notice I dropped 'self.'

    ...

  end

  ...

end

然后在您的 class 中添加:

class ProductionProductivity7 < ApplicationRecord
  extend ProductionProductivity7sHelper

  ...

end

这会将模块中定义的所有方法添加为 ProductionProductivity7 的 class 方法。注意:这假设您省略的方法也是 class 方法,即以 'self.'

开头