Abs
Abs

Reputation: 2324

Breaking the Rails-flavored REST

Rails beginner here.

I'm trying to create a web application dashboard that shows system statistics like CPU, memory, disk usage, etc.

No databases will be used, so I suppose models won't be required. I'll have views and controllers.

I have a URL pattern in mind: /dashboard/sys_stats/CPU/load, /dashboard/sys_stats/CPU/utilization, /dashboard/sys_stats/memory/free, etc.

With my limited exposure to Rails, I know controller#action maps to a URI of the form /controller/action. My questions are:

  1. What should be my controller and actions?
  2. Since controller and action allow only 2-levels in URI, i.e., /controller/action, how do I get a long URI like the ones I mentioned above.
  3. In a way, CPU and memory statistics are my model. I just don't know if I should have the logic to read CPU/memory statics from OS in controller and not create a model, or create a model class. I think model is where it belongs, but correct me if I'm wrong. Since Rails model is associated with a DB, I don't know how to include logic to read from OS in model.

Upvotes: 0

Views: 124

Answers (2)

Michelle Tilley
Michelle Tilley

Reputation: 159095

It's difficult to answer these questions entirely and completely without knowing the full extent of the application (plus there are multiple ways of going about some of these things), but I will answer based on the information you've given and how I might go about doing things.

1. What should be my controller and actions?

Rails controllers are usually named for, and contain methods that manage, an individual resource. A resource an be any domain concept; often, they map one-to-one with your Rails models, but they don't have to.

In your case, you could go a couple of directions:

  1. Have a controller for each of the stat "types" (e.g. CPU, memory, etc.) with actions for each "stat" (free, total, etc.)
  2. Have a controller for "sys_stats" with actions for each type

This decision could depend on how the rest of your app is structured; if sys_stats is the only thing the app is concerned with, maybe it makes more sense to go for the former.

2. Since controller and action allow only 2-levels in URI, i.e., /controller/action, how do I get a long URI like the ones I mentioned above.

You have fairly good control over URL generation via the Rails routing system. You can find a ton of specific details on the Rails Routing from the Outside In guide, but if you went with the controller/action layout #1 (discussed above), it might look something like this:

get "dashboard/sys_stats/:controller/:action"

3. In a way, CPU and memory statistics are my model.

Yes, and building the app this way will make it easier to test and very likely easier to work on and maintain. It's important to remember that you can have a model (even in app/models) without requiring that the class extends ActiveRecord::Base in any way. With the right abstraction, your controllers needn't even know that your models aren't tied to a database.


I've started a little demo app that demonstrates some of these concepts; you can find it on GitHub at https://github.com/BinaryMuse/so16493562-rails-stats-example.

Some of the relevant files:

config/routes.rb

RailsSystemStats::Application.routes.draw do
  get "dashboard/sys_stats/:controller/:action"
end

app/controllers/memory_controller.rb

class MemoryController < ApplicationController
  before_filter do
    @memory = MemoryStat.new
  end

  def free
    respond_to do |format|
      format.html
      format.json do
        render json: { memory: { free: @memory.free } }
      end
    end
  end

  def total
    respond_to do |format|
      format.html
      format.json do
        render json: { memory: { total: @memory.total } }
      end
    end
  end
end

app/models/memory_stat.rb

class MemoryStat
  def initialize
  end

  def free
    6.5.gigabytes
  end

  def total
    8.gigabytes
  end
end

(Obviously you'd replace this class with one that actually got system details.)

Upvotes: 2

Rafi
Rafi

Reputation: 545

  1. It's hard to tell what your controllers should be from just two functionalities. To me, it seems like a good way would be to have one controller per type of statistic (cpu, memory, etc), and an action in each for the specific statistic (utilization, etc). Your routes are a big hint to this -- as you pointed out, URLS are usually controller/action (do you really need sys_stat in every URL?) -- so you can get a lot of info from how you've been thinking about your routes.

  2. In Rails, you can make custom routes:

http://guides.rubyonrails.org/routing.html

This way, you can have any route point to any controller and action. For example, to have /dashboard/sys_stats/CPU/load point to controller memory, actions free:

match '/dashboard/sys_stats/memory/free' => 'memory#free'

Of course, enumerating each one this way will be tedious (but gives you more control); you can read the routing docs to see how you can make this more efficient.

  1. System calls in Ruby are made through system: http://ruby-doc.org/core-2.0/Kernel.html

Models are not necessarily associated with the DB -- but the general rule is fat models, skinny controllers. If you find yourself typing a lot of logic in the controller, factor it out to a model. If it's just a few lines, then keep it there. The controller should just be directing requests to models and views.

Hope that helps!

Upvotes: 1

Related Questions