【问题标题】:Where to put method that combines two models结合两种模型的方法放在哪里
【发布时间】:2015-01-28 15:07:33
【问题描述】:

我是 Ruby 和 Rails 的新手。

我有一个方法,查询两个不同的数据模型,合并结果,返回合并结果

def combine_models
    ...
end

该方法当前驻留在控制器中。我想将方法​​移动到模块或类(仍然不确定是哪个),以便该方法可以在多个控制器中使用。

1) 最好放在哪里?

2) 应该是模块还是类?

3) .rb 文件的内容是什么样的?

目前我有它在/models/combine_class.rb。文件内容为:

class CombineClass
    def combine_models
        ...
    end
end

该类似乎是自动加载的,但要调用该方法我必须使用CombineClass.new.combine_models

4) 这是调用该方法的正确方法吗?有没有办法可以在没有.new. 的情况下调用该方法?

【问题讨论】:

  • 回答 4) 仅当您将方法设为 staticclass 方法时
  • 为了澄清 Nermin 的评论,您可以将 def combine_models 更改为 def self.combine_models。另外,如果您不存储任何状态,我会将其设为模块,将方法保留为 def combine_modelsincludeApplicationController 中。
  • @ptd 感谢您的澄清。我已将其从类更改为模块。我将include CombineClass 添加到ApplicationController,但现在出现错误:undefined method 'combine_models' for CombineClass:Module。我也试过require 'combine_class',但得到同样的错误。

标签: ruby-on-rails ruby


【解决方案1】:

我建议你阅读这篇文章:Structuring Rails Applications 并将你的逻辑提取到 app/usecases/model1_model2_combiner_usecase.rbapp/models 并不是一个真正适合这样做的地方),它可能看起来像这样:

class Model1Model2CombinerUsecase
  def self.run
    ...
  end
end

当然要正确地重命名它,然后在你的控制器中调用它

@combined_models = Model1Model2CombinerUsecase.run

【讨论】:

  • 这正是我想要的。我一直在研究这个问题并想使用app/projectname/file_name.rb,但由于我没有使用def self.run,所以无法让它工作。
【解决方案2】:

我建议放入模型目录的关注文件夹中。

模型/关注/combine_models.rb:

module CombineModels
  extend ActiveSupport::Concern

  def combine_model1_model2
    ...
  end
end

在您的模型中,您可以包含模块:

class Model1
  include CombineModels

  ...
end

class Model2
  include CombineModels

  ...
end

您可以在每个模型中使用您的 combine 方法,其中包括 CombineModels 模块

【讨论】:

    【解决方案3】:

    将你的类留在模型目录中实际上并没有什么问题,尽管最新的 Rails 约定是让它成为一个问题。

    如果您只想要两个模型的某些属性的聚合,并且您的组合类没有要实现的其他行为,我会采用这样的简单解决方案。

    class CombineFooAndBar
      def self.combine_models(f, b)
        f.x + b.y
      end
    end
    
    class Foo
      attr_accessor :x
    end
    class Bar
      attr_accessor :y
    end
    
    f = Foo.new
    f.x = 2
    b = Bar.new
    b.y = 3
    
    puts "CombineFooAndBar value is #{CombineFooAndBar.combine_models(f,b)}"
    

    如果您以后需要更多行为,那么我会在那时将其重构为关注点。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多