Patm
Patm

Reputation: 2075

Rails Logic in controllers?

I am always reading about keeping Controllers thin and doing all logic in models. While this makes senses to me for interacting with databases, what about situations where there is no need to for database interactions?

I have a fairly complex module in my app that interact with several different third party APIs. I use ajax calls to my controller, where all the data is gathered from the APIs and then organized. Then it is displayed via the corresponding .js.erb or .html.erb files.

Is this the proper way to handle this kind of situation? I'm new to rails and don't want to get into habit of doing things wrong.

Upvotes: 7

Views: 4067

Answers (3)

yfeldblum
yfeldblum

Reputation: 65455

Do model logic in models.

  • Maintain associations.
  • Maintain complex attributes.
  • Maintain validations.
  • Represent concepts from the business/industry.

Do controller logic in controllers.

  • Check that a user is authorized to modify a resource.
  • Pull and aggregate data to pass into a view template.
  • Find the right view template.
  • Compose json for the API response.
  • Retry failed saves.

Models do not need to be ActiveRecords. You can do a whole lot with models - the "core" of your appliation - that has nothing to do with persistence. Just don't put controller logic into these models.

Upvotes: 4

Scott
Scott

Reputation: 17257

That's a good question.

Even if you don't need to use a database, you can still take an OOP / MVC approach to organise your code and wrap your data, logic and behaviour in models.

Code organisation and encapsulation within model objects is still useful & important!

In Rails 3, you can make non-persisting models by including just some of the ActiveModel modules that ActiveRecord contains. For example:

# This class exists as a fairly simple DTO that is not expected to be persisted, but 
# it does have validation, attributes & a hash constructor, just like ActiveRecord models
class MyProduct
  include ActiveModel::Conversion
  include ActiveModel::Naming
  include ActiveModel::Validations

  attr_accessor :title, :quantity

  validates :title, :quantity, :presence => true
  validates :quantity, :numericality => {:greater_than_or_equal_to => 1}

  def initialize(attributes = {})
    attributes.each do |name, value|
      send("#{name}=", value)
    end
  end

  def persisted?
    false
  end
end

Upvotes: 2

fl00r
fl00r

Reputation: 83680

Models are not just for dealing with database, but for working with data in principle.

As far as we don't know what situations you mean I can just present some situations.

Ajax call for big Math calculating. It is not touching database and even it can be calculating in tableless model.

# in your controller
def calculating
  Calculator.get_integral_log_and_furie params[:data]
end
# in your model
class Calculator
  def self.get_integral_log_and_furie(data)
    ... # multi line code
  end
end

So you can see that you can calculate it right in your controller, but it should be calculated in your model, so it is reusable and clean solution.

Another example is using some virtual attributes. Names. You can store first, second and third name in saparate columns, so you need to join it. You can create privae method in controler, but of course it is bad idea.

class User < AR::Base
  def full_name
    [first_name, second_name, third_name].compact.join(" ")
  end
end

So you can call it everywhere in your project:

@user.full_name
# Peter Jhonson, or mu is too short

And so on and so on

Upvotes: 8

Related Questions