Here are some notes about variables, scoping, etc.
Variables in Ruby/Rails are of your fairly standard variety (local, instance, public). There is another type called “class” or “class instance” variables that get way too much attention for the amount they are used (or not used) in most apps. If you are learning Ruby/Rails, just ignore Class Variables for now and don’t use them.
As with most languages/frameworks, it’s the “visibility” of variables that is important. This is especially true with web-based applications. Ruby is based on MVC (Model/View/Controller) architecture (see http://betterexplained.com/articles/intermediate-rails-understanding-models-views-and-controllers/ for a good MVC overview)
In the diagram shown at the website referenced above, notice that the Browse interacts with the Controller, which gets data from the Model, then passes it back using the View.
Models, View, and Controllers are just classes. Rails hides their complexity making them seem like magic, but they are just Ruby classes.
Models are ActiveRecord classes
Views are ActionView classes
Controllers are ActionController classes
Controllers and Views have a special arrangement though, since both of them are part of ActionPack. This means they actually share a codebase. (see http://ap.rubyonrails.com/ for a thorough a picture and an explanation)
…snippet… “Action Pack splits the response to a web request into a controller part (performing the logic) and a view part (rendering a template). This two-step approach is known as an action, which will normally create, read, update, or delete (CRUD for short) some sort of model part (often backed by a database) before choosing either to render a template or redirecting to another action. Action Pack implements these actions as public methods on Action Controllers and uses Action Views to implement the template rendering. Some of the features, are tied to ActiveRecord, but that doesn’t mean that Action Pack depends on Active Record. Action Pack is an independent package that can be used with any sort of backend.”
What this means for you, is that instance variables defined in a Controller are visible to any View called by that controller.
Local Variable
current_time = Time.now
If defined in a Controller, it can NOT be seen from “any” View called by the Controller.
Instance Variable
@current_time = Time.now
Can be seen only from “this” instance of this class
If defined in a Controller, it can be seen from “any” View called by the Controller.
Class (instance) Variable
@@current_time = Time.now
Can be seen and changed from “any” instance of this class (one variable shared across all instances)
If defined in a Controller, it can be seen from “any” View called by the Controller.
Public/Global Variable
$current_time = Time.now
Can be seen and changed from “anywhere”
An Example
\app\controllers\application.rb
$current_time = Time.now # Global Variable (visible everywhere)
Controller
class OrdersController < ApplicationController
def index
@orders = Tblorder.find_recent_orders # Call Model Method “find_recent_orders”
@filter_scope_name = “Recent Orders” # Set Instance Variable (visible by view)
render :action => ‘list’ # Show the View
end
end
Model
class Order < ActiveRecord::Base
@filter_recent_days = 15 # Instance Variable (NOT visible by view because this is the Model)
def self.find_recent_orders
# “sql” is a local variable (not visible anywhere else)
sql = “SELECT * FROM orders where DATEDIFF(curdate(), ordDateOrderTaken) <= “ + @filter_recent_days.to_s
find_by_sql(sql)
end
end
View
<!– Most of the HTML is in \app\views\layouts\orders.rhtml –>
<% if @orders.length == 0 then%>
<p> No Orders Exist.</p>
<% else %>
<% if @filter_scope_name %> # Using Instance Variable from Controller
<caption><%= h @filter_scope_name %></caption>
Current Time: <%= $current_time %> # Using Global Variable from file application.rb
<% else %>
<caption>Order List</caption>
<% end %>
<% end %>
<% for order in @orders -%>
<%= link_to order.id, :action => ’show’ %> <br />
<%= order.ordCustPONum %> <br />
<%= order.ordOEM %> <br />
<%= order.ordDescription %> <br />
<%= order.ordModelNum %> <br />
<%= order.ordSerialNum %> <br />
<%= order.ordFinalDisposition %> <br />
<%= order.ordDateOrderTaken %> <br />
<% end %>
A Note About Controller Methods
Even though your Controller Instance Variables will be visible to your View, your Controller Methods will not. You can get around this by placing methods that need visibility to the View in your Controller Helper (app\helpers\orders_helper.rb based on our example above).