Skip to content
December 4, 2010 / mattdyor

Notes on Rails

This works along with Simply Rails: http://my.safaribooksonline.com/9780980455205

To start developing, go to terminal > documents/rails/rallywire then type ruby script/server, then you can visit it at http://0.0.0.0:3000

To play around with your application in the console, terminal to the directory and type ruby script/console

1.    Get to the irb
⁃    go to terminal and type irb
⁃    This lets you play with ruby
2.    Create the rails app
⁃    In terminal, go to the folder in which you want you application to be created (e.g., cd MattDyor/Documents/Rails is where I put all of my rails apps), and type rails APPLICATION_NAME
⁃    rails RallyWire
3.    Create the model
⁃    open terminal
⁃    terminal browse to the directory of the application (create it in finder if you need to)
⁃    terminal rails script/generate model RallyPoint name:string
⁃    fixed by running rails RallyWire – confirm and removei needed to copy the files from the archive over to get this to work
⁃    generating the model automatically adds an id, created_at, and updated_at
⁃    terminal rake db:migrate
4.    Naming conventions:
⁃    Use nouns as your class nouns (eg-use Subscription instead of Subscribe)
⁃    This means you are describing what you are storing, not what you are doing
⁃    Camelcase the class (Subscription, RallyPoint)
⁃    lowercase and pluralize the table (subscriptions, rally_points)
⁃    most references other than the class are lowercase (eg-the resources in the config)
⁃    instance variables can be small, but should be lower
⁃    attributes of the class are lower case
5.    Now add data to the model
⁃    terminal ruby script/console
⁃    rp = RallyPoint.new
⁃    rp.name = ‘Clubhouse Rally’
⁃    rp.save
6.    Now create the controller
⁃    ruby script/generate controller RallyPoints index (note the plural here and not above)
⁃    this will create our index page only
⁃    the controller that is created is rally_point
⁃    update the index method in the controller
⁃    def index
⁃    @rally_point = RallyPoint.find_by_name(‘Clubhouse Rally’)
⁃    end
7.    Now update the view file (index.html.erb)
⁃      <p><%= @rally_point.name%></p>
8.    Firing up the server
⁃    ruby script/server
⁃    you should be able to visit at 0.0.0.0:3000
9.    Add a form to create new entries
⁃    In textmate, go to app>views>XXX(datatype), right click and select new
⁃    Call the file new.html.erb
⁃    <% form_for @rally_point do |f|%>
⁃    <p>
⁃    name: <br />
⁃    <%= f.text_field :name%>
⁃    </p>
⁃    <p>
⁃    <%= submit_tag %>
⁃    </p>
⁃    <% end %>
⁃    update the controller–add a new method
⁃    @rally_point = RallyPoint.new
10.    Now add the helper URLs to map URLs to functions
⁃    go to config/routes.rb
⁃    add map.resources :rally_points
⁃    Now you should be able to visit 0.0.0.0:3000/rally_points/new
11.    A brief review
⁃    The route directory is /rally_points (plural)
⁃    In the config/routes.rb, there is the update above and the following
⁃    map.root :controller => “rally_points”
⁃    the class is RallyPoint, everything else is rally_point
12.    Create your create method in the controller
⁃    def create
⁃    @rally_point  = RallyPoint.new(params[:rally_point])
⁃    @rally_point.save
⁃    redirect_to rally_points_path
⁃    end
13.    Test your controller
⁃    navigate to /rally_point/new
⁃    create a record
⁃    fire up an irb console (terminal > cd to project directory, ruby script/console)
⁃    Story.find(2)
⁃    Story.find(:all)
⁃    Story.find(:all).last
⁃    Story.find(:first, :order =>  ‘id DESC’)
⁃    Story.find_by_name(‘Hello World Today’)
⁃    Story.find(:first, :order => ‘RANDOM()’)
14.    Create your layout
⁃    create, in ap>views>layouts, a layout named application.html.erb
⁃    standard XHTML web page with two extra fields: stylesheet under the title and yield in the body
⁃    <%= stylesheet_link_tag ‘style’ %>
⁃    this will point the style sheet to /public/stylesheets/style.css
⁃    <div id=”content”>
⁃    <%= yield %>
⁃    </div>
15.    Create your style sheet
⁃    body
⁃    {
⁃    background-color: #666;
⁃    margin: 15px 25px;
⁃    font-family: Helvetica, Arial, sans-serif;
⁃    }
⁃    #content
⁃    {
⁃    background-color: #fff;
⁃    border: 10px solid #ccc;
⁃    }
16.    Add some flash
⁃    In the style.css
⁃    #notification {
⁃    border: 5px solid #9c9;
⁃    background-color: #cfc;
⁃    padding: 5px;
⁃    margin:; 10px 0;
⁃    }
⁃    in the controller, add this line after the .save command
⁃    flash[:notice] = ‘Rally Point submission succeeded.’
⁃    add this to your index.html.erb
⁃    <% unless flash[:notice].blank? %>
⁃    <div id=”notification”><%= flash[:notice] %></div>
⁃    <% end %>
17.    Validation
⁃    add this to the model (app/models/rally_point.rb) inside the class
⁃    validates_presence_of :name
⁃    now update the controller>create method so that it does not redirect if there is a (validation) problem
⁃      if @rally_point.save
⁃            flash[:notice] = ‘Rally Point submission succeeded.’
⁃            redirect_to rally_points_path
⁃        else
⁃          render :action => ‘new’
⁃        end
⁃    add this to new.html.erb
⁃    <%= error_messages_for ‘rally_point’ %>
18.    Now create unit tests
⁃    unit tests are defined in test>unit>rally_point_test.rb
⁃    def test_should_not_be_valid_without_name
⁃    rp = RallyPoint.create(:name=>nil)
⁃    assert rp.errors.on(:name)
⁃    end
⁃    def test_should_create_story
⁃        rp=RallyPoint.create(:name=>’Big Juicy Unit Test’)
⁃        assert rp.valid?
⁃      end
⁃    run your unit tests in terminal with rake test:units
19.    Now create functional tests
⁃    functional tests are defined in test>functional?rally_points_controller_test.rb
⁃      def test_should_show_index
⁃        get :index
⁃        assert_response :success
⁃        assert_template ‘index’
⁃        assert_not_nil assigns(:rally_point)
⁃      end
⁃    run your functional tests with rake test:functionals
⁃        assert_select ‘form p’, :count => 3
⁃    Test the create method:
⁃      def test_should_add_rally_point
⁃    post :create, :rally_point => {
⁃          :name => ‘test from test’
⁃        }
⁃        #new_record? tests whether you have a new, unsaved record
⁃        assert ! assigns(:rally_point).new_record?
⁃        #i am not sure whether this actually saves it to the database…it does not appear to have
⁃        assert_redirected_to rally_points_path
⁃        assert_not_nil flash[:notice]
⁃      end
⁃    you can run all the tests with rake test
20.    Create the user security bits
⁃    ruby script/generate model User login:string password:string name:string email:string phone:string
⁃    go to the created model (db/migrate/XXXcreate user.rb) and add this line outside of the create_table and inside self.up:
⁃    add_column :rally_points, :user_id, :integer
⁃    add this to the self.down after drop_table
⁃    remove_column :stories, :user_id
⁃    rake db:migrate
⁃    in the user model, add has_many :rally_points
⁃    in the rally_point model, add belongs_to :user
⁃    Create the sessions controller for managing login (note: this is sessions…with an s, not sure why)
⁃    ruby script/generate controller Sessions new create destroy
⁃    including new create and destroy adds the methods and creates the templates
⁃    update routes.rb with this (note the singular–this is a singleton object, meaning that each user can have only one session)
⁃    map.resource :session
⁃    since this is singular, all of the urls will be singular (eg., session/new)
⁃    update the new.html.erb file
⁃    <% form_tag session_path do %>
⁃      <p>Please log in.</p>
⁃      <p>
⁃        <label>Username: </label>
⁃        <%= text_field_tag ‘ login’ %>
⁃      </p>
⁃      <p>
⁃        <label>Password: </label>
⁃        <%= password_field_tag ‘ password’ %>
⁃      </p>
⁃      <p><%= submit_tag ‘ login’ %></p>
⁃    <% end %>
⁃    update sessions_controller.rb (in app>controllers)
⁃      def create
⁃        @current_user = User.find_by_login_and_password(params[:login], params[:password])
⁃        if @current_user
⁃          session[:user_id] = @current_user.id
⁃          redirect_to rally_points_path
⁃        else
⁃          flash[:notice]=”Incorrect username or password. Please try again.”
⁃          render :action=>’new’
⁃        end
⁃      end
⁃    current_user = User. find session[:user_id]
21.    Apply a login filter
⁃    Add this code to the application_controller (app/controller/)
⁃      before_filter :fetch_logged_in_user
⁃        protected
⁃          def fetch_logged_in_user
⁃            return unless session[:user_id]
⁃            @current_user = User.find_by_id(session[:user_id])
⁃          end
⁃    Add this code to the application layout (app/views/layout)
⁃            <div id=”login_logout”>
⁃          <% if @current_user %>
⁃            Logged in as:
⁃            <%= @current_user.login %>
⁃            <em><%= link_to “(Logout) “, session_path,  :method => :delete %></em>
⁃          <% else %>
⁃            <em>Not logged in.</em>
⁃            <%= link_to ‘Login’, new_session_path %>
⁃          <% end %>
⁃        </div>
⁃    Add the formatting to the style sheet (public/stylesheets)
⁃    #login_logout {
⁃      float: right;
⁃      color: #999;
⁃      font-size: smaller;
⁃    }
⁃    Add this to the session_controller (app/controllers)
⁃      def destroy
⁃        session[:user_id] = @current_user = nil
⁃      end
⁃    Update your logout page
⁃    <h2>Logout successful</h2>
⁃    <%= link_to ‘Back to the home page’ , rally_points_path %>
⁃    Add Navigation to the template (within the body)
⁃      <ul id=”navigation”>
⁃        <li><%= link_to ‘Front page rally points’, rally_points_path %></li>
⁃        <li><%= link_to ‘Submit a new rally point!’, new_rally_point_path %></li>
⁃      </ul>
⁃    Helper methods for requiring login before visiting pages by updating the applicationcontroller (below the protected)
⁃    def logged_in?
⁃        ! @current_user. nil?
⁃      end
⁃      helper_method :logged_in?
⁃    NOTE: the second helper method is so that you can access this method in the views (first method is for access via controller)
⁃    And then add this that actually requires the user to login
⁃    def login_required
⁃        return true if logged_in?
⁃        session[:return_to] = request.request_uri
⁃        redirect_to new_session_path and return false
⁃      end
⁃    Update the rally_points_controller right under the class Intro
⁃     before_filter :login_required, :only => [ :new, :create ]
⁃    Replace the redirection line on sessions_controller with this:
⁃    session[:user_id] = @current_user.id
⁃          if session[:return_to]
⁃            redirect_to session[:return_to]
⁃            session[:return_to] = nil
⁃          else
⁃            redirect_to rally_points_path
⁃          end
⁃    Associate a user with a story by replacing the top line of the create method of the rally_points_controller with the following line
⁃     @rally_point = @current_user.rally_points. build params[:rally_point]
⁃    And show the user along with their story
⁃    <%= @rally_point.user.login %>
⁃    You may need to delete all your rally points or update them so that they have a
23.    Code snippets
⁃    <%= link_to @rally_point.name, @rally_point.link %>
⁃    <%= link_to “New”, new_rally_point_path %>
⁃    url helpers are rally_points_path [/rally_points], rally_point_path(@rally_point) [/rally_points/1], edit_rally_point(@rally_point) [/rally_points/1/edit)

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: