Ruby on Rails Cheat Sheet
rails 데이터 타입
:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean
Rails Mimetype
"./." => :all
"text/plain" => :text
"text/html" => :html
"application/xhtml+xml" => :html
"text/javascript" => :js
"application/javascript" => :js
"application/x-javascript" => :js
"text/calendar" => :ics
"text/csv" => :csv
"application/xml" => :xml
"text/xml" => :xml
"application/x-xml" => :xml
"text/yaml" => :yaml
"application/x-yaml" => :yaml
"application/rss+xml" => :rss
"application/atom+xml" => :atom
"application/json" => :json
"text/x-json" => :json
bundle asset precompile
bundle exec rake assets:precompile RAILS_ENV="production"
rake assets:clean<
add below code if you want development environment with out precompile
config.serve.static.assets = false
application.rb
use Bundler.require(:default, :assets, Rails.env) instead of Bundler.require(*Rails.groups(:assets => %w(development test)))
compile assets locally
Put below into development.rb
config.assets.prefix = "/temp-assets"
Also put below into application.rb
config.assets.initialize.on.precompile = false
rails logger
Rails.logger.info "My info message"
Rails.logger.debug "My debugging message"
Rails.logger.warn "My warning message"
Environment Log level
config.log_level = :debug, :info, :warn, :error, and :fatal
Validation text length CR filter
before.validation :replace.cr
protected
def replace.cr
if self.description.changed?
self.description.gsub!(/\r\n?/, "\n")
end
end
validation locale
// config/locales/en.yml
en:
activerecord:
attributes:
user:
email: "E-mail address"
errors:
models:
user:
attributes:
email:
blank: "is required"
If you are using mongoid, replace activerecord: with mongoid:
Validate associated
The answer to this turned out to be rather simple. On the parent model, you simply explicitly declare that you want the associated children validated.
parent.rb
validates_associated :children
Validate if persisted? or new_record?
validates.uniqueness.of :nickname, :message => I18n.t("user.already.taken"), :if => :new.record?
validates.uniqueness.of :nickname, :message => I18n.t("user.already_taken"), :unless => :persisted?
Session Store in rails 3
Use the database for sessions instead of the cookie-based default, which shouldn't be used to store highly confidential information
Create the session table with
rake db:sessions:create
Run the migration
rake db:migrate
Make sure you also tell rails to use ActiveRecord to manage your sessions too.
Rails 3
config/initializers/session.store.rb:
Rails.application.config.session.store :active.record.store
DB Migrate Production
rake db:migrate RAILS_ENV="production"
get rails environment
Rails.env
env["SERVER_NAME"]
rails template
rake print --silent RECIPES=jquery,haml,rspec,cucumber,guard,mongoid,action.mailer,devise,add.user,home.page,home.page.users,seed.database,users.page,css.setup,application.layout,html5,navigation,cleanup,ban.spiders,extras,git,compass,omniauth,omniauth.email,backbone > ~/Desktop/backbone.template.txt
Could you please run it again using the "-T -O -J" flags? As in
rails new template_test -m https://github.com/fortuity/rails3-application-templates/raw/master/rails3-mongoid-devise-template.rb -T -O -J
http://blog.dominicsayers.com/2011/08/16/howto-use-a-rails-template-from-github-on-windows/
thin start
D:\dev\ruby192\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) D:/dev/workspace/baksisi/script/rails server thin -b 127.0.0.1 -p 3002 -e development
ruby ./script/rails server thin -b smoke-free-online.de -p 3000 -e development -d
thin start
Middle Man
"server" was called incorrectly. Call as "middleman server [-p 4567] [-e development]".
"middleman server [-p 4567] [-e development]" instead of "middleman server -p 4567 -e development
DB migration
Rails g migration change.data.type.for.table_column
I18n
locale join
config/application.rb
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '.*', '..{rb,yml}')]
locale path
routes.rb
match '/:locale' => "home#index"
root :to => "home#index"
scope "/:locale" do
controller :models do
something
end
resources :models, :only => :show
ApplicationController
def default.url.options(options = {})
options.merge!({:locale => I18n.locale})
end
Localize
I18n.l Time.now, :format => :short, :locale => :"ko"
Pluralization
ko:
pears:
zero: ko.zero
one: ko.one
few: ko.few
other: ko.other
generate rake tasks
rails g task namespace task1 task2
rake -T | grep namespace
세션 저장
config.session.store :cookie.store, :key => '.baksisi.session', :domain => :all
environment.rb 메일러에 레이아웃을 지정하고 싶다면.
DeviseMailer.layout "OMG"
show routes
rake routes
SASS
config/application.rb:
config.generators.stylesheet_engine = :sass
sass-convert style.sass style.scss
Trouble Shootings
uninitialized constant
file name confirm (if file name capital, it can be occurred.)
guard-livereload error
gem install eventmachine --pre
open-uri.rb file in C:/Ruby1.9.2/lib/ruby/1.9.1/ (of course your path might be different).
http.verify.mode = options[:ssl.verify.mode] || OpenSSL::SSL::VERIFY.NONE
[ERROR] V8 is no longer usable
ulimit -v unlimited
CSV Data Handling
http://www.ruby-doc.org/stdlib-1.9.2/libdoc/csv/rdoc/CSV.html
get action information at view
params[:action]
HAML
rails helper using haml
def section(name)
haml.tag(:div, :class => 'section') do
haml.tag(:h2, name)
haml.tag(:p, :class => 'section.content') do
yield
end
end
end
def content.box
haml.tag :div, :class => "holder" do
haml.tag :div, :class => "top"
haml.tag :div, :class => "content" do
yield
haml.tag :div, :class => "bottom"
end
end
and in haml
%html
%head
%body
Maybee some content here.
- content.box do
Content that goes in the content_box like news or stuff
fields_for with index
<% @questions.each.with.index do |question,index| %>
<% f.fields.for :questions, question do |fq| %>
# here you have both the 'question' object and the current 'index'
<% end %>
<% end %>
It’s also possible to specify the instance to be used:
<%= form.for @person do |person.form| %>
...
<% @person.projects.each do |project| %>
<% if project.active? %>
<%= person.form.fields.for :projects, project do |project.fields| %>
Name: <%= project.fields.text_field :name %>
<% end %>
<% end %>
<% end %>
<% end %>
Rails Response
namespace "api" do
resources :regions, :defaults => { :format => 'xml' }
end
Then you should be able to have the following work for your controller methods:
class Api::RegionsController < ApplicationController
respond.to :xml, :json
def index
respond.with(@regions = Region.all)
end
end
rescue.from ActionController::MissingFile do |e|
# User's browser probably wont display this
# Content-Type is application/x-shockwave-flash
render :file => File.join(Rails.public.path, '404.html'), :status => 404
end
show details or stream video
def show
@media = Media.find params[:id]
respond.to do |format|
format.html
format.flv { send.file @media.path, :disposition => 'inline' }
end
end
render :file => File.join(Rails.public.path, '404.html'), :status => 404, :content.type => 'text/html'
render with variable
render :partial => "my/conejo", :locals => {:my.val => something}
render "my/liebre", :my.val => something
scope
default_scope order('id DESC')
Model.reorder('')
Model.unscoped
render an other action in the controller, in js.
render 'result', :id => @item.id, :format => :js
layout xhr?
class ApplicationController < ActionController::Base
layout proc{|c| c.request.xhr? ? false : "application" }
end
layout :layout.xhr?
def layout.xhr?
request.xhr? ? false : 'application'
end
AJAX Performance stale? and touch
def show
@list_item = @list.list_items.find( params[ :id ] )
if stale?( :etag => @list_item, :last_modified => @list_item.updated_at.utc, :public => true )
respond_with( @list_item )
end
end
Also instead of the update_list method being called from after_save/destroy you can pass :touch => true to the belongs_to association which will do the same
AJAX Handler - ?xhr
respond_with( @something, :layout => !request.xhr? )
or
respond_to do |wants|
wants.html do
if request.xhr?
render :partial => "items"
else
render
end
end
end
Asset
exist
YourApp::Application.assets.find_asset("#{asset}.file").nil?
### pathname
<YourAppName>::Application.assets.find_asset('Rails.png').pathname
absolute asset_path in view using helper
"#{request.protocol}#{request.host.with.port}#{asset.path('person/gravatar.default.png')}"
"#{request.scheme}://#{request.host.with.port}#{request.script_name}"
Mailer
config
environment/production.rb
config.action.mailer.default.url.options = {:host => 'localhost:3000',:locale =>I18n.locale}
config.action.mailer.smtp.settings = {
:address => "server.addr",
:port => 587,
:domain => "sever.domain",
:user.name => "user.name",
:password => "user.password",
:authentication => "plain",
:enable.starttls.auto => true
}
config.action.mailer.delivery.method = :smtp
config.action.mailer.perform.deliveries = true
config.action.mailer.raise.delivery.errors = false
config.action.mailer.default :charset => "utf-8"
inline attachement
in mailer
attachments.inline['blank'] = {
:data => File.read("#{Rails.root.to.s + '/app/assets/images/blank.png'}"),
:mime.type => "image/png",
:encoding => "base64"
}
in view
if @offer.image.nil?
= image.tag( attachments['blank'].url, :id => 'attachement.image', :width => "400", :height => "400")
validates in I18n
%{attribute} - field name
%{model} - model name
%{count} - count
rescue log
begin
...some code...
rescue Exception => e
logger.error e.message
Ruby
Iterate
a.each.with.index do |item, index|
puts item, b[index]
end
array.each.slice(3) do |elements|
fire.the_event
end
Timezone
in client (js):
function set.time.zone.offset() {
var current.time = new Date();
$.cookie('time.zone', current.time.getTimezoneOffset());
}
in Application Controller:
before.filter :set.timezone
def set.timezone
min = request.cookies["time.zone"].to_i
Time.zone = ActiveSupport::TimeZone[-min.minutes]
end
DateTime format
%a - The abbreviated weekday name (Sun)
%A - The full weekday name (Sunday)
%b - The abbreviated month name (Jan)
%B - The full month name (January)
%c - The preferred local date and time representation
%d - Day of the month (01..31)
%H - Hour of the day, 24-hour clock (00..23)
%I - Hour of the day, 12-hour clock (01..12)
%j - Day of the year (001..366)
%m - Month of the year (01..12)
%M - Minute of the hour (00..59)
%p - Meridian indicator (AM or PM)
%S - Second of the minute (00..60)
%U - Week number of the current year,
starting with the first Sunday as the first
day of the first week (00..53)
%W - Week number of the current year,
starting with the first Monday as the first
day of the first week (00..53)
%w - Day of the week (Sunday is 0, 0..6)
%x - Preferred representation for the date alone, no time
%X - Preferred representation for the time alone, no date
%y - Year without a century (00..99)
%Y - Year with century
%Z - Time zone name
%% - Literal ``%'' character
t = Time.now
t.strftime("Printed on %m/%d/%Y") #=> "Printed on 04/09/2003"
t.strftime("at %I:%M%p") #=> "at 08:56AM"
datetime seconds, hours, days, weeks, months, and years
Add below lines to one of your initializer files, e.g., config/environment.rb:
DateTime::DATE.FORMATS[:short]="short %Y-%m-%d %H:%M:%S"
Time::DATE.FORMATS[:short] = "short %Y-%m-%d %H:%M:%S"
Date::DATE.FORMATS[:short] = "short %Y-%m-%d"
modify view:
<%= item.create_date.to_s(:short) %>
distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
today = DateTime.now
=> #<DateTime: 441799066630193/180000000,-301/1440,2299161>
birthday = Date.new(2008, 4, 10)
=> #<Date: 4909133/2,0,2299161>
days_to_go = birthday - today
time_until = birthday - today
=> Rational(22903369807, 180000000)
time_until.to_i # get the number of days until my birthday
=> 127
hours,minutes,seconds,frac = Date.day_fraction.to_time(time_until)
[3053, 46, 57, Rational(1057, 180000000)]
- mm = (now-la st_cigarette).divmod(Rational(1, 1440))[0]
- past.days = mm / 1440
- past.hours = (mm % 1440) / 60
- past_minutes = mm % 60
timezone
def set_api_time_zone
utc_offset = current.user.session && current.user.session.user ? current.user.session.user.time.zone.offset.to.i.minutes : 0
user.timezone = ActiveSupport::TimeZone[utc.offset]
Time.zone = user.timezone if user.timezone
Time.zone.today
Time.now.to.date
# => Thu, 19 May 2011
Time.now.in.time.zone('Melbourne').to_date
# => Fri, 20 May 2011
end
Range step
range.step(2) {|x| puts x}
benchmark
require 'benchmark'
n = 1000000
def answer1 current.subdomain
case current.subdomain
when 'www', 'blog', 'foo', 'bar'
else nil
end
end
def answer2 current.subdomain
nil unless ["www", "blog", "foo", "bar"].include?(current.subdomain)
end
Benchmark.bmbm do |b|
b.report('answer1'){n.times{answer1('bar')}}
b.report('answer2'){n.times{answer2('bar')}}
end
Rehearsal -------------------------------------------
answer1 0.290000 0.000000 0.290000 ( 0.286367)
answer2 1.170000 0.000000 1.170000 ( 1.175492)
---------------------------------- total: 1.460000sec
user system total real
answer1 0.290000 0.000000 0.290000 ( 0.282610)
answer2 1.180000 0.000000 1.180000 ( 1.186130)
Benchmark.bmbm do |b|
b.report('answer1'){n.times{answer1('hello')}}
b.report('answer2'){n.times{answer2('hello')}}
end
Rehearsal -------------------------------------------
answer1 0.250000 0.000000 0.250000 ( 0.252618)
answer2 1.100000 0.000000 1.100000 ( 1.091571)
---------------------------------- total: 1.350000sec
user system total real
answer1 0.250000 0.000000 0.250000 ( 0.251833)
answer2 1.090000 0.000000 1.090000 ( 1.090418)
출처