Ruby On Rails Code Snippets


Table Of Contents

External Resources / Tutorials

Rails Conventions and Notes

- Controllers are Named Single, Models are Plural. - Create models (scaffolds etc) with Singular names, rails will pluralize everything (model User becomes table Users)

Generate A Controller

# From The Command Line:
rails generate controller Store index
					

Generate a Scaffold And Migrate DB

# Generate a Model named Product (database table named products)
# As well as a title, a description, an image URL, and a price column
#
# From The Command Line:
rails g scaffold Product title:string description:text image_url:string price:decimal

# Now apply the Migration. From the Command Line:
rake db:migrate
					

Delete A Scaffold

# To delete "blog" scaffold, from the command line:
rails destroy scaffold blog
					

Roll Back A Database Migration

# From The Command Line:
rake db:rollback
					

Simple Form And Controller (Without Model)

Generate A Form on your View
# replace root_path with your path
<%= form_tag root_path, :method => 'POST' do %>
  <%=label_tag 'First Name' %>
  <%=text_field_tag 'first_name'%>
  <%= submit_tag 'Submit' %>
<% end %>
					


Now Modify Your Controller...
class WhateverController < ApplicationController
  def index
    @submitted_name = params[:first_name]
  end
end
					


Be Sure To Add A Post To Your Routes File
post "/" => 'whatever#index'
					

Push Code To Heroku

# From Command Line, check that Heroku Toolbelt is installed
heroku --version

# Enter email address and password to login to Heroku
heroku login

# Add your SSH keys
heroku keys:add

# Add a heroku app
heroku create

# Remove sqlite3 db from gemfile, add to development section of gemfile then bundle without dev
bundle install --without development

# Push Code
git add .
git commit -am "message"
git push
git push heroku master
					

Create HTML Blog editing forms with TinyMCE

#Add TinyMCE gem to gemfile to create a wordpress editor on blog creation/writing pages.
# Use .html_safe tag on output variables so the HTML gets executed
					

Flash Messages With Bootstrap

Put This In A Partial...
<% flash.each do |name, msg| %>
  <div class="alert alert-warning alert-dismissible">
    <button class="close" data-dismiss="alert">
      <i class="glyphicon glyphicon-remove-circle"></i>
    </button>
    <%= content_tag(:div, msg) %>
  </div>        
<% end %>
					

Validate Form Fields

# From your app/models/whatever.rb file add the line:
validates :title, :description, :image_url, presence: true

# where :title, :description, etc are your form fields
					


Set Conditions on your validation, ie on price:
validates :price, numericality: {greater_than_or_equal_to: 0.01}
					


Test for Uniqueness
validates :title, uniqueness: true
					


Test for Regex
validates :image_url, allow_blank: true, format: {
  with:    %r{\.(gif|jpg|png)\Z}i,
  message: 'must be a URL for GIF, JPG or PNG image.'
 }
					

Create Common Content All Controller Actions Can Access

To Create Variables That All Actions in a Controller Can Access...
# In...say...a home_controller.rb file
class HomeController < ApplicationController
  # Specify Which Actions Can Use Your Common Content
  before_action :common_content, :only => [:index, :show]

  def common_content
  @random_number = (1..100)
  end

  def index
  end

  def show
  end

  # now you can use the @random_number instance variable on the index.html.erb and show.html.erb view pages
					

Pull Data From Database & Show It On The Page

# From Your app/controllers/whatever_controller.rb
def index
	@products = Product.order(:title)
end
					


Then Edit Your View...
<% @products.each do |product| %>
    <%= image_tag(product.image_url) %>
    <h3><%= product.title %></h3>
    <%= sanitize(product.description) %>
      <%= product.price %>
<% end %>
					

Enable Caching in Dev Environment

# From /config/environments/development.rb enable cache then restart server
config.action_controller.perform_caching = true
					


Then Change /app/models/product.rb
class Product < ActiveRecord::Base
.
.
  def self.latest
    Product.order(:updated_at).last
  end
end
					


Next Update Your Store Views Where product changes may be...
# above product loop:
<% cache ['store', Product.latest] do %>
	.
	#under product loop
	<% cache ['entry', 'product'] do %>
	.
	.
	<% end %>
<% end %>
					

Pass URL Param into Variable (with routing)

In Your Routes File
# where (:item) is the variable you want in your url and the ()'s make it optional
get 'home/index(/:item)' => "home#index"
# or for more than one item:  get 'home/index(/:category(/:item))' => "home#index"
					


Then modify your home/index controller
# create instance variable
@item = params['item']

# check to see if an item was listed
if @item == nil
  # do nothing
else
# replace and underscores _ with blank spaces
  @item = @item.gsub(/_/, " ")
end
					


Finally use your @item instance variable wherever you want in your view
The URL will look like this:
http://yourURL.com/home/index/fender_deluxe_stratocaster_guitar
					


...Which will pass fender_deluxe_stratocaster_guitar to your instance variable
and remove underscores, leaving you with "Fender Deluxe Stratocaster Guitar"

** Note: you don't even need the home/index if you want to do it on the root...
# Routes file:
get '(/:category(/:item))', to: "home#index"
# Then do the same controller stuff in your home/controller
# And the output URL will look like this:
http://yourURL.com/guitars/fender_deluxe_stratocaster_guitar
# Where your @category instance variable will be "guitars" 
# and your @item instance variable will be "fender deluxe stratocaster guitar"
					

Add or Remove Another Column To A Pre-Existing Database

# From The Command Line:
rails generate migration AddSomethingToTablename addsomething:string
# Where AddSomething is the thing you want to add and Tablename is the table you're adding too
rake db:migrate
# Note: You then have to update your views and controller manually for CRUD actions
#
# To add several things: 
rails generate migration AddFieldsToTablename first_name:string last_name:string age:integer
# then rake db:migrate
#
#To Remove a Column
rails g migration remove_field_name_from_table_name field_name:datatype
					

Roll Back A Database Migration (to fix an error)

# To Roll back the last migration, From The Command Line:
rake db:rollback

# To Roll back some other previous migration (where n is the number back you want to go...)
rake db:rollback STEP=n
					

Add Fake Database Data With The Seeds.rb File

# From db/seeds.rb
Whatever.create ([:user_name => "myName#{rand(1..100)}",
	:first_name => "John", 
	:last_name => "Elder", 
	:age => "38",
	:description => "blah blah blah"
	])
# Where Whatever is your db table, and the :first_name etc fields are your database columns found in your schema file
# and #{rand(1..100)} creates a random number so the username is unique every time we seed (and fools any validation) the database!

# From the Command Line:
rake db:seed
					


To randomize all the fields, use the linguistics gem or faker gem...
#Add to gemfile:
gem 'linguistics'
gem 'faker'

# then bundle install from command line					
					


Then change your db/seed.rb file:
# Let's create 100 records
100.times do
	Whatever.create ([:user_name => "#{Faker::Internet.user_name}",
		:first_name => "#{Faker::Name.first_name}", 
		:last_name => "#{Faker::Name.last_name}", 
		:age => "#{rand(15..120)}",
		:description => "#{Faker::Lorem.paragraph}"
		])
end

# From the Command Line:
rake db:seed
			

Delete all the Data from Database (but don't delete database)

# Where Whatever is the name of your database table
Whatever.destroy_all

# Easy => Slap Whatever.destroy_all into your seeds.rb file and then rake db:seeds, or do it from the console
					

DB Console Stuff

# Pull up Rails Console From Terminal
rails console

# Pull in database called User:
User.connection

# Show all records
User.all

# See first record
User.first

# See last record
User.last

# Count records
User.count

# Search records
User.where(:last_name => "Elder")

# Change something in a record, like first_name (set user into a variable)
a = User.first
# Make your changes
a.first_name = "Bob"
# Save the change to the database
a.save

# Delete all records in the database (but don't delete the table)
User.destroy_all
					

Associating 2 Models (Blog and Comments)

# Say we have a Blog model and want to create a Comment model for comments. From command line:
rails generate scaffold Comment title:string author:string content:text blog:references
# Where blog:references is the foreign key that associates the Comment model with the Blog model
rake db:migrate  #Run the migration
					


Then in your comment.rb file:
belongs_to :blog
					


Then in your blog.rb file:
has_many :comments, :dependent => :destroy #:dependent => :destroy tells rails to delete comments if you delete a blog post
					


To Seed Fake Comments using Faker (add it to gemfile), change your db/seed.rb file:
# Let's create 100 records
100.times do
	Blog.create ([:user_name => "#{Faker::Internet.user_name}",
		:first_name => "#{Faker::Name.first_name}", 
		:last_name => "#{Faker::Name.last_name}", 
		:age => "#{rand(15..120)}",
		:description => "#{Faker::Lorem.paragraph}"
		])

	blog.save
	rand(0..10).times do
	Blog.comments.create([:title => "#{Faker::Internet.user_name}",
		:author => "#{Faker::Name.first_name}", 
		:comment => "#{Faker::Name.last_name}"
		])
	end
end

# From the Command Line:
rake db:seed

					


Now Add your comment code to your blog show.html.erb view page to show all comments
<% blog.comments.each |comment| do %>
  <h3><%= comment.title %></h3>
  <h3><%= comment.author %></h3>
  <p><%= comment.content %></p>
  <hr/>
<% end %>

					


Now Add A Form on your blog show.html.erb at the bottom to add a new comment
# You can grab the form from the comments scaffold and past it onto your blog show page
# But you need to post the form and associate it with the blog post at the same time for @comment
<%= form_for(@comment) do |f| %>
.
.
 # change the blog_id form field to hidden
.
.
<% end%>
					


So on your Blog Controller (show controller)
def show
  @comment = Comment.new
end
					


Now We Need To Update Our Routing & Add Nested Route (so comment form works)
# in routes.rb move resources :comments line into nested resources :blog do block
resources:blog do
	resources :comments
end
					


Now We need to update our Comment form to add the Blog post so it knows which post to add the comment to
# on your blog show view, add @blog reference (notice the array [ ])
<%= form_for([@blog, @comment]) do |f| %>
.
.
<% end%>
					


Now update the Comment Create Controller
def create
  @blog = Blog.find(params[:blog_id])
  @comment = @blog.comments.new(comment_params)
  # @comment = Comment.new(comment_params)
 
  # Then Save and Redirect, but not to @comment, we want to redirect to @blog
  respond_to do |format|
	  if @comment.save
	        format.html { redirect_to movie_path( @blog ), notice: "Comment was successfully created." }
		format.jason { render action: 'show', status: :created, location: @comment}
	  else
	    format.html { redirect_to movie_path( @blog ), notice: "Comment was not created."  }
	    format.jason { render json: @comment.errors, status: :unprocessable_entity }
	  end
  end
end
					

Validating Model Form Fields

# From your app/models/whatever.rb file
validates :description,  presence: true, length: { maximum: 140 }
validates :user_name, presence: true, uniqueness: true
					

Create Unique Titles on application.html.erb for each Page of Site

# On Each Page/View of Your Site...
<% content_for :title, "Your Unique Title" %>

# Then in your layouts/application.html.erb file...
<!DOCTYPE html>
<html>
<head>
  <title><%= yield(:title) %></title>
  .
  .
  .
					

Designate Different Paths for Routes

# In Your Routes file...
resources :blogs, path: "whatever"
# Now your route would be www.yoursite.com/whatever/6 instead of yoursite.com/blogs/6
					

Change Default Number for RESTFUL Url's in Model

# In Your app/model/Model.rb file...
def to_param
  # change spaces in title to hyphens -
  title.gsub!(/\s/,'-')
  #change URL from ID to ID-Title
  "#{id}-#{title}"
end
					

Use Blog Titles's as URL's

# In Your app/model/Model.rb file...
def to_param
  # change spaces in title to hyphens -
  title.gsub!(/\s/,'-')
  #change URL from ID to Title
  "#{title}"
end
					


# In Your Routes file...
resources :blogs, path: '' #, param: :title
# path: '' changes the path to root url
					


# In Your Controller...
private
    # Use callbacks to share common setup or constraints between actions.
  def set_blog
  	#replace spaces in title with hyphens
	@spaces = (params[:title]) 
	@spaces.gsub!('-',' ')
	# find the blog post to output using find_by_title instead of just find
	#@blog =  Blog.find_by(title: (params[:title]))
	#@blog = Blog.find_by_title(params[:id])
	@blog = Blog.find_by_title(@spaces)
      
  end