Topic: RoR doesn't seem to follow it's own Fat Model Skinny Controller patter

First, I'll start off with the obligatory (yet annoying), "I'm a newbie to Ruby on Rails" blah blah blah.  In fact, I am fairly new to OOP in general, but I think I understand the 5-minute basics of OOP. 

I have been creating a basic site by following along in the book "Agile Web Development with Rails".  I've also been reading about the concept of skinny controller / fat model and I think I get it, generally speaking.  While following along with the book, I created my basic database, model, controller, and view.  When I look at the code that Rails generated, it is anything but skinny controller / fat model.

My controller:

class GlucoseLogsController < ApplicationController
  # GET /glucose_logs
  # GET /glucose_logs.xml
  def index
    @glucose_logs = GlucoseLog.all

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @glucose_logs }
    end
  end

  # GET /glucose_logs/1
  # GET /glucose_logs/1.xml
  def show
    @glucose_log = GlucoseLog.find(params[:id])

    respond_to do |format|
      format.html # show.html.erb
      format.xml  { render :xml => @glucose_log }
    end
  end

  # GET /glucose_logs/new
  # GET /glucose_logs/new.xml
  def new
    @glucose_log = GlucoseLog.new

    respond_to do |format|
      format.html # new.html.erb
      format.xml  { render :xml => @glucose_log }
    end
  end

  # GET /glucose_logs/1/edit
  def edit
    @glucose_log = GlucoseLog.find(params[:id])
  end

  # POST /glucose_logs
  # POST /glucose_logs.xml
  def create
    @glucose_log = GlucoseLog.new(params[:glucose_log])

    respond_to do |format|
      if @glucose_log.save
        format.html { redirect_to(@glucose_log, :notice => 'Glucose log was successfully created.') }
        format.xml  { render :xml => @glucose_log, :status => :created, :location => @glucose_log }
      else
        format.html { render :action => "new" }
        format.xml  { render :xml => @glucose_log.errors, :status => :unprocessable_entity }
      end
    end
  end

  # PUT /glucose_logs/1
  # PUT /glucose_logs/1.xml
  def update
    @glucose_log = GlucoseLog.find(params[:id])

    respond_to do |format|
      if @glucose_log.update_attributes(params[:glucose_log])
        format.html { redirect_to(@glucose_log, :notice => 'Glucose log was successfully updated.') }
        format.xml  { head :ok }
      else
        format.html { render :action => "edit" }
        format.xml  { render :xml => @glucose_log.errors, :status => :unprocessable_entity }
      end
    end
  end

  # DELETE /glucose_logs/1
  # DELETE /glucose_logs/1.xml
  def destroy
    @glucose_log = GlucoseLog.find(params[:id])
    @glucose_log.destroy

    respond_to do |format|
      format.html { redirect_to(glucose_logs_url) }
      format.xml  { head :ok }
    end
  end
end

My model:

class GlucoseLog < ActiveRecord::Base
end

What am I missing?  Is it just because I haven't added any validation or special data logic yet?  Still the controller seems pretty lengthy.

Thanks.

Re: RoR doesn't seem to follow it's own Fat Model Skinny Controller patter

You are missing nothing (except that OO skills take a lot longer than 5 minuites to pick up lol smile)
Think about what is happening here

  def index
    @glucose_logs = GlucoseLog.all

    respond_to do |format|
      format.html # index.html.erb
      format.xml  { render :xml => @glucose_logs }
    end
  end

When lookuing at this GlucoseLog.all statement think about the following
Where is the connection to the database?
Where is the SQL?
Where is the error handling and exception raising? It sure isn't in the controller smile
If the answer to that question was in the controller then every single controller action would have another 600 plus lines of code added to it.
Have a good look at what the ActiveRecord class gives you and you start to get the idea that it's better to put all that functionality in one base class from which all classes that need access to the database can use.
As you have a basic understanding of OO development I'm sure you'll be extending the ActiveRecord class yourself before long and writing gems and plugins rather than RoR apps

Business logic belongs in the model in an MVC architecture right? So when you start actually cutting Rails code think twice before adding anything to the controller. Most of your code should be going in to the model layer.

hope that helps

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)

Re: RoR doesn't seem to follow it's own Fat Model Skinny Controller patter

Thanks a lot James.  I think I get it.  I'll keep what you said in the back of my mind and then come back with more questions if I don't get it.  Thanks again.

Re: RoR doesn't seem to follow it's own Fat Model Skinny Controller patter

Ok James,

Along those same lines, I was trying to follow the flow of the order that files are accessed from the browser all the way to the model.  Please see this image here to see what I'm talking about.

First of all, does this image make sense?  Second, is it correct?

Also, based on what you said earlier, the model then calls ActiveRecord, correct?  Where can I see the ActiveRecord class?

Thanks again for your help.  By the way, if you think this is getting off topic, please suggest where I could create a separate post for this.

Re: RoR doesn't seem to follow it's own Fat Model Skinny Controller patter

I just realized that my flow chart is incorrect.  Shouldn't it actually be Browser --> glucose_logs_controller.rb --> glucose_log.rb (model) --> glucose_logs_controller.rb --> HERE'S WHERE I GET CONFUSED (new.html.erb or _form_html.erb) ?

Re: RoR doesn't seem to follow it's own Fat Model Skinny Controller patter

Wow, this is really heavy and in depth stuff! Are you sure you really want to get into this at this stage?

based on what you said earlier, the model then calls ActiveRecord, correct?

No that's totally wrong. I think this is where you really need to understand OO development. If you are from a linear development background (which from your posts I suspect you are) you are REALLY going to struggle with this as you need a total and uitter mind shift in your approach and thought process about the structure of your apps. you have to totally stop thinking about procedures and think about objects. As I said earlier this is a really hard concept that most developers from a linear background never quite (some argue (not me) that none ever get) get but I'm not getting into a debate about that here.

This is all about object inheritance. Class Two descends from Class One
Like so

Class Two < One
end

class one looks like this

Class One
  def self.time_now
    Time.now
  end
end

simple enough
This means that an object instance of class Two will have a method available called time_now. This method and functionality are in the object not in some external entity that the object calls.
This is a very distinct difference between calling a method on a dll for example and I find myself thinking back to the days of V.B. and Delphi and endless V.B. developers trying to convince me that V.B. was an OO language lol!

OK you can now descend any number of classes from class one and they will all have that method available to them and it becomes part of the class/object

In walks ActiveRecord. It's just one of many classes. Bear in mind that absolutely Everything in ruby is a class even an integer and a string for example, again this is quite something for linear developers to get their head round! and Activerecord is just a class with a bunch of functionality that you can descend your own classes from and they will automatically inherit the functionality of AR. OO is massively powerfull and hopefully you should now start getting the idea that if you can make sure you only ever write and extend classes you will find that you will never have to add any more code to a controller action and you will automatically be following the principle of MVC and indeed your controller classes could actually be totally empty with just a class declaration!

Where can I see the ActiveRecord class?

I use netbeans (6.9) as my IDE and I can just ctrl click on the class declaration and it will open up the file concerned but you will find the files inside the bin folder of your Ruby installation (Bearing in mind that if you have frozen your gems that could be in your vendors folder in the root of your app. Just do a search for base.rb in your file system you will find the active record module in there. Also have a look at this railscast
http://railscasts.com/episodes/239-acti … alkthrough

I just realized that my flow chart is incorrect.  Shouldn't it actually be Browser --> glucose_logs_controller.rb --> glucose_log.rb (model) --> glucose_logs_controller.rb --> HERE'S WHERE I GET CONFUSED (new.html.erb or _form_html.erb) ?

Ahh! Back to simpler stuff
A request comes into your server and this is picked up by typically in a production environment) passenger. Passenger routes the request to your app by looking in your routes.rb file (In your config folder).
Your routes thend etermine which controller and action gets called or even if the method is allowed or exists. so ALL requests go through your routes.rb file then the action in the controller whcih then has to render something or :nothing

Shouldn't it actually be Browser --> glucose_logs_controller.rb --> glucose_log.rb (model) --> glucose_logs_controller.rb --> HERE'S WHERE I GET CONFUSED (new.html.erb or _form_html.erb) ?

It renders both!
Take the following example
navigate to some_app/glucose_log/new (as a standard html get request) and you will end up inside the action called new in your glucose_logs.rb controller (assuming all things are eaqual and your routes are set up that way)

Rails will pick up the fact that you should have a file called new.html.erb in a folder called glucose_logs inside your applications views folder and this is what will get rendered.
This view embeds the partial view called _form.html.erb by using a

<%= render 'form' %>

Rails expects this to be a file called form.html.erb prefixed with an underscore to denote that it's a partial to live in the same folder as the containing template so if creating a partial to be used on every single page of your app (A header or a footer for example) you might want to put that in the views/shared folder (creating the folder if it's not there) and call it like so

  <%= render '/shared/header' %

Indeed if you yield that in your applications layout then whatever you put inside the file called _header.html.erb will be included on every single page of your application.

so what about ajax, xml and the likes?
well restfull routes will give you all that by default you just need to define the templates adnd sort out what you want to render in the respond_)to blocks in your controller actions. Go on give it a try
Navigate to glucose_logs/index.xml and see what happens smile

What you want and what you need are too often not the same thing!
When your head is hurting from trying to solve a problem, stop standing on it. When you are the right way up you will see the problem differently and you just might find the solution.
(Quote by me 15th July 2009)