Tod Birdsall
Tod Birdsall

Reputation: 19015

Where to put method that combines two models

I am new to Ruby and new to Rails.

I have a method that queries two different data models, combines the results and returns the combined results

def combine_models
    ...
end

The method currently resides in a controller. I want to move the method to a module or class (still unsure which) so that the method can be used in multiple controllers.

1) Where is the best place to put this?

2) Should it be a module or a class?

3) What would the contents of the .rb file look like?

Currently I have it in /models/combine_class.rb. The contents of the file are:

class CombineClass
    def combine_models
        ...
    end
end

The class appears to auto load, but to call the method I must use CombineClass.new.combine_models.

4) Is that the proper way to call the method? Is there a way I could call the method without .new.?

Upvotes: 0

Views: 113

Answers (3)

mhinton
mhinton

Reputation: 1175

There's nothing actually wrong with leaving your class in the models directory although the newest Rails convention is to make it a concern.

If you only want the aggregate of some property of the two models and there isn't other behavior that your combination class is going to implement I would go with a simple solution like this.

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)}"

If you need more behavior later then I would refactor it to a concern at that time.

Upvotes: 0

Klaus
Klaus

Reputation: 1771

I suggest to put in into the concerns folder of the model dir.

models/concerns/combine_models.rb:

module CombineModels
  extend ActiveSupport::Concern

  def combine_model1_model2
    ...
  end
end

In your models you can include the module:

class Model1
  include CombineModels

  ...
end

class Model2
  include CombineModels

  ...
end

You can use your combine methods in every model, which includes the CombineModels module

Upvotes: 0

Rustam Gasanov
Rustam Gasanov

Reputation: 15781

I would recommend you to read this article: Structuring Rails Applications and extract your logic into app/usecases/model1_model2_combiner_usecase.rb( app/models isn't really a good place for this), which may look like this:

class Model1Model2CombinerUsecase
  def self.run
    ...
  end
end

Of course rename it properly, then just call it in your controller with

@combined_models = Model1Model2CombinerUsecase.run

Upvotes: 1

Related Questions