Created
November 16, 2011 12:31
-
-
Save azinazadi/1369968 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
' | |
rails 1.9 new hash syntax | |
new_hash = {simon: "Talek", lorem: "Ipsum"} | |
###Rspec | |
%cucumber | |
save_and_open_page | |
###MIGRATION | |
Methods: | |
create_table(name, options) | |
drop_table(name) | |
rename_table(old_name, new_name) | |
add_column(table_name, column_name, type, options) | |
rename_column(table_name, column_name, new_column_name) | |
change_column(table_name, column_name, type, options) | |
remove_column(table_name, column_name) | |
add_index(table_name, column_name, index_type) | |
remove_index(table_name, column_name) | |
change_table(table_name) {|Table.new(table_name, self)| ...} | |
change_column_default(table_name, column_name, default) | |
change_column_null(table_name, column_name, null, default = nil) | |
Available Column Types (mappings are below): | |
* integer | |
* float | |
* datetime | |
* date | |
* timestamp | |
* time | |
* text | |
* string | |
* binary | |
* boolean | |
* decimal :precision, :scale | |
Valid Column Options: | |
* limit | |
* null (i.e. ":null => false" implies NOT NULL) | |
* default (to specify default values) | |
* :decimal, :precision => 8, :scale => 3 | |
Rake Tasks: | |
rake db:schema:dump: run after you create a model to capture the schema.rb | |
rake db:schema:import: import the schema file into the current database (on | |
error, check if your schema.rb has ":force => true" on the create table | |
statements | |
./script/generate migration MigrationName: generate a new migration with a new | |
'highest' version (run './script/generate migration' for this info at your | |
fingertips) | |
rake db:migrate: migrate your current database to the most recent version | |
rake db:migrate VERSION=5: migrate your current database to a specific version | |
(in this case, version 5) | |
rake db:rollback: migrate down one migration | |
rake db:rollback STEP=3: migrate down three migrations | |
rake db:migrate RAILS_ENV=production: migrate your production database | |
rake db:create RAILS_ENV='test' #create the test database | |
SQL: | |
Queries can be executed directly: | |
execute 'ALTER TABLE researchers ADD CONSTRAINT fk_researchers_departments | |
FOREIGN KEY ( department_id ) REFERENCES departments( id )' | |
Example Migration: | |
class UpdateUsersAndCreateProducts < ActiveRecord::Migration | |
def self.up | |
rename_column "users", "password", "hashed_password" | |
remove_column "users", "email" | |
User.reset_column_information | |
User.find(:all).each{|u| #do something with u} | |
create_table "products", :force => true do |t| | |
t.column "name", :text | |
t.column "description", :text | |
t.column "price", :decimal, :precision => 9, :scale => 2 | |
t.column "category_id", :integer | |
end | |
#the rails 2.0 way: | |
create_table :people do |t| | |
t.integer :account_id | |
t.string :first_name, :last_name, :null => false | |
t.text :description | |
t.references :category # is the equivalent of t.integer :category_id | |
t.timestamps | |
end | |
end | |
def self.down | |
rename_column "users", "hashed_password", "password" | |
add_column "users", "email", :string | |
drop_table "products" | |
end | |
end | |
Find Highest version: | |
script/runner "puts ActiveRecord::Migrator.current_version" | |
Database Mapping | |
Rails db2 mysql openbase Oracle | |
:binary blob(32678) blob object blob | |
:boolean decimal(1) tinyint(1) boolean number(10) | |
:date date date date date | |
:datetime timestamp datetime datetime date | |
:decimal decimal decimal decimal decimal | |
:float float float float number | |
:integer int int(11) integer number(38) | |
:string varchar(255) varchar(255) char(4096) varchar2(255) | |
:text clob(32768) text text clob | |
:time time time time date | |
:timestamp timestamp datetime timestamp date | |
Rails postgresql sqlite sqlserver Sybase | |
:binary bytea blob image image | |
:boolean boolean boolean bit bit | |
:date date date datetime datetime | |
:datetime timestamp datetime datetime datetime | |
:decimal decimal decimal decimal decimal | |
:float float float float(8) float(8) | |
:integer integer integer int int | |
:string * varchar(255) varchar(255) varchar(255) | |
:text text text text text | |
:time time datetime datetime time | |
:timestamp timestamp datetime datetime timestamp | |
Version 7, updated 140 days ago. | |
' | |
chp 12 | |
5:50 | |
fri | |
11:34 - 12:30 work on exercises of ajax | |
try to put it in line items not on store controller . | |
tue | |
10:30 - 12 | |
10:15 - 11 | |
turn | |
10:30 - 12 | |
3 - 5 | |
thursday | |
12:50 - 14 | |
3 - 4:11 * localization | |
7 - 8:30 | |
friday | |
11:50 - 12:20 | |
2:20 - 3:20 | |
17 - 18:10 Active Records | |
6:40 - | |
saturday | |
8 - 9 | |
11:30 - 12 | |
2 - 2:30 | |
*** ITINERARY RECEIPT *** | |
AGENCY/AIRLINE NAME DATE OF ISSUE 19AUG11 | |
AVIAREPS AG WALLDORF FRANKFURT RLOC W5 - Q7RTF | |
NAME: AZADIYAZDI/ATIN MRS | |
E-TICKET NUMBER: 5372100349460 | |
DATE FLIGHT DEPARTURE AIRPORT ARRIVAL AIRPORT TIME CLASS BAG | |
21AUG W5 5059 DUS-DUSSELDORF, GERMAN IKA-IMAM KHOMEINI - TE 1145 V -OK 40K | |
02OCT W5 5060 IKA-IMAM KHOMEINI - TE DUS-DUSSELDORF, GERMAN 0620 T -OK 40K | |
RESTRICTIONS: NON-END/FARE CODE W5-413/MAX WEIGHT PER PIECE 23KG/ REF | |
50EUR NOSHOW 50EUR | |
FORM OF PAYMENT: MISC/CP/INVOICE//AZAD/108086 | |
FARE: BASE IT EUR | |
TAX/FEE/CHARGE 3.75DE/25.00OY/56.85XT | |
TOTAL IT EUR | |
Notice: "Carriage and other services provided by the carrier are subject to | |
conditions of carriage, which are hereby incorporated by reference. | |
These conditions may be obtained from the issuing carrier." | |
#RAKE | |
rake --tasks | |
rake -T | |
rake routes | |
rake --describe task:name:and:options | |
rake db:create RAILS_ENV='test' | |
class Post < ActiveRecord::Base | |
validates_presence_of :title, :body | |
validates_uniqueness_of :title | |
end | |
Some people consider testing validations to be useless because I can be pretty sure that Rails has already done so. Considering validations are probably the lowest level of architecture in my models, it's a good idea just to verify that they're doing what I think they're doing. | |
describe Post do | |
before(:each) do | |
@post = Post.new(valid_post_hash) # grabs the hash below | |
end | |
it "should be valid" do | |
@post.should be_valid | |
end | |
it "should not be valid without a title" do | |
@post.title = '' | |
@post.should_not be_valid | |
end | |
it "should not be valid without a body" do | |
@post.body = '' | |
@post.should_not be_valid | |
end | |
def valid_post_hash | |
{:title => 'test', :body => 'test body'} | |
end | |
end | |
RSpec is not as readable as many would like it to be, but hopefully it's readable enough that I don't need to explain the above. I will mention some optional items that could be put in there: | |
before(:all) do | |
# this will be run once before all examples in this describe block | |
end | |
before do | |
# same as before(:each) | |
end | |
after(:each) do | |
# this will be run once after each example | |
@post.destroy unless @post.new_record? | |
end | |
after(:all) do | |
# this will be run once after all examples in this describe block | |
# Useful tasks to put in here are: | |
Post.destroy_all | |
end | |
Strings: | |
'foo'.should == 'foo' | |
'foo'.should === 'foo' | |
'foo'.should_not equal('foo') | |
''.should be_empty | |
'foo with bar'.should include('with') | |
'http://fr.ivolo.us'.should match(/http:\/\/.+/i) | |
nil.should be_nil | |
Numbers: | |
100.should < 200 | |
200.should >= 100 | |
(200 - 100).should == 100 | |
# (100 - 80) is less than 21 | |
100.should be_close(80,21) | |
Arrays: | |
[1,2,3].should have(3).items | |
[].should be_empty | |
[1,2,3].should include(2) | |
Hashes: | |
{}.should be_empty | |
{:post => {:title => 'test'}}.should have_key(:post) | |
{:post => {:title => 'test'}}.should_not have_key(:title) | |
false.should be_false | |
true.should be_true | |
Records: | |
# assuming @post = Post.new(:title => 'test') | |
@post.should be_instance_of(Post) | |
@post.should respond_to(:title) | |
MOCKING | |
describe PostsController, "comment", :behaviour_type => :controller, do | |
before do | |
@post = mock_model(Post) | |
Post.should_receive(:find).and_return(@post) | |
@comment = mock_model(Comment) | |
Comment.should_receive(:new).with.({:title => 'comment title', :body => 'comment body'}).and_return(@comment) | |
@blogger = mock_model(User) | |
@controller.instance_variable_set(:@blogger, @blogger) | |
end | |
it "should add comments to the post" do | |
@comment.should_receive(:save).and_return(true) | |
@post.comments.should_receive(:concat).and_return(@comment) | |
post :comment, :id => @post.id, :comment => {:title => 'comment title', :body => 'comment body'} | |
flash[:notice].should match(/success/i) | |
response.should redirect_to(posts_path(@blogger, @post)) | |
end | |
end | |
L A M B D A | |
Ever done something ugly like this? | |
old_count = Article.count | |
@article.tags.create(...) | |
Article.count.should == old_count+1 | |
Here''s a better way: | |
lambda { @article.tags.create(...) }.should change(Article, :count).by(1) | |
Other possibilities include: | |
lambda { @article.tags.create(...) }.should change(Article, :count).from(0).to(1) | |
lambda { @article.title = 'new title' }.should change(@article, :title).to('new title') | |
2. Ever done this in TestUnit? | |
assert_raises (ActiveRecord::RecordNotFound) do | |
Article.find(0) | |
end | |
Heres how you can do that in rspec: | |
lamda{ Article.find(0) }.should raise_error(ActiveRecord::RecordNotFound) | |
#GIT | |
to modify a commit | |
You can use git rebase, for example, if you want to modify commit bbc643cd, run | |
$ git rebase bbc643cd^ --interactive | |
In the default editor, modify 'pick' to 'edit' in the line whose commit you want to modify. Now you can use | |
$ git commit --amend | |
to modify the commit, and after that | |
$ git rebase --continue | |
to return back to the previous head commit. | |
#BASH | |
tails -f logfile | |
##Active Records | |
#CRUD | |
@order = Order.new(params[:order]) | |
total = Product.find(product_list).sum(&:price) | |
cart = Cart.find_or_initialize_by_user_id(user.id) | |
cart.items << new_item | |
cart.save | |
also: Cart.find_or_create_by... | |
#SQL and ActiveRecord | |
pos = Order.where(["name = ? and pay_type = 'po'", name]) | |
pos = Order.where("name = :name and pay_type = :pay_type", {:pay_type = pay_type, :name => name}) | |
pos = Order.where(:name => params[name], :pay_type => params[:pay_type]) | |
User.where("name like ?", params[:name]+"%") | |
%Order Limit Offset | |
orders = Order.where(:name => 'Dave').order("pay_type, shipped_at DESC").limit(10).offset(page_num*page_size) | |
%Select Join => the result will be readonly | |
LineItem.select('li.quantity'). | |
where("pr.title = 'ruby programming'"). | |
joins("as li inner join products as pr on li.product_id = pr.id") | |
%group | |
summary = LineItem.select("sku, sum(amount) as amount").group("sku") | |
%lock => we offen use transactions instead | |
%getting column statistics | |
average = Order.average(:amount) | |
" maximum | |
" minimum | |
" sum(:amount) | |
" count | |
result = Order.where("amount > 20").maximum(:price).group(:state) #=> [["TX",123],["NC",354]] | |
%scopes | |
class Order... | |
scope :last_n_days, lambda { |days| where('updated < ?', days) } | |
... | |
last_week = Order.last_n_days(7) | |
scope :checks, where(:pay_type => :check) | |
last_week_checks = Order.checks.last_n_days(7) | |
-> take care of using order and limit only once in total chain of scopes | |
#writin ur own sql | |
orders = Order.find_by_sql("select name, pay_type from orders") | |
%reload data | |
stock.reload | |
#update | |
order.save | |
order.update_attribute(:name, "Barney") | |
order.update_attributes(:name => "Barney", :email => "@") | |
order.update_attributes(params[:order]) | |
%read and update using id as reference | |
order = Order.update(12, :name => "barney") | |
-> it can also be used to update multiple rows | |
result = Product.update_all("price = 1.1*price", "title like '%Java'") | |
-> updates all products price by 10% which have Java in their title | |
-> usually return the number of affected rows (DB dependent) | |
# save, save!, create, create! | |
##Action Dispatch and Action Controller | |
Action Pack = Action Dispatch + Action Controller + Action View | |
REST = Representational State Transfer | |
-> update -> put | |
** rake routes -> show | |
%Seven Methods and urls | |
index (products_url or path), new (new_product_url), create, show (product_url), edit (edit_product_url), update, destroy | |
%limiting routed actions | |
resources :comments, :except => [:update, :destroy] | |
%Adding Additonal Actions | |
resources :products do | |
get :who_bought, :on => :member #or :on => :collection | |
#Nested Resources | |
resources :products do | |
resources :reviews | |
end | |
-> the path to review must be prefixed with a product: /products/99/reviews/4 | |
-> named_route: product_review | |
%Shallow Route Nesting | |
resources :products, :shallow => true do | |
resources: reviews | |
end | |
/products/1/reviews => product_reviews_index_path(1) | |
/reviews/2 => reviews_path(2) | |
%Formats | |
/store/show/1.xml | |
/store/show/1?format=xml | |
respond_to do |format| | |
format.yaml { render :text => @product.to_yaml } | |
end | |
#Testing Routes | |
... | |
##Processing of Requests | |
%Action Methods (How does a responsing method get found in a controller) | |
1- a public method with the same name as the incomming action | |
2- method_missing method of the controller | |
3- a template named after the current controller and action | |
4- UnknownAction error | |
%Controller Environment | |
* action_name | |
* cookies | |
* headers | |
* params | |
* request | |
* request_method => :delete, :get, :head, :post, :put | |
* method => the same as request_method except head... | |
* delete?, get?, head?, post?, put? | |
* xml_http_request? or xhr? => is it ajax? dependent of request | |
* url => the full URL | |
* protocol, host, port, path, query_string => protocol://host:port/path?query_string | |
* domain => the last two components of the domain name | |
* host_with_port => "host:port" | |
* port_string | |
* ssl? | |
* remote_ip => multiple ips if behind proxy | |
* path_without_extension, path_without_format_and_extension, format_and_extension | |
* env => like, request.env['HTTP_ACCEPT_LANGUAGE'] | |
* accepts => accepts value of the mime type of request | |
* format => value of content-type of request | |
* mime_type | |
* content_type | |
* headers => complete set of http headers | |
* body :the request body as an I/O stream | |
* content_length: number of bytes purported to be in the body | |
* response | |
* session | |
* logger | |
* Renderin Templates | |
-> default template path: app/views/CONTROLLER/ACTION.TYPE.XXX where type is html, atom or js and XXX is erb or builder or rjs etc. | |
%Render method | |
* render(:text => "hello") #no template interpretation | |
* render(:inline => string, [:type => "erb, builder or rjs"], [:locals => hash]) #interpret string as a template | |
* render(:file => path, [:use_full_path => true|false]) #renders a file | |
* render(:template => "blog/short_list", ...) | |
* render(:partial => name, ...) | |
* render(:nothing => true) #sends an empty body to the client | |
* render(:xml => stuff) #sends stuff as text, forcing the content type to be application/xml | |
* render(:json=> stuff, [:callback => hash]) #like xml. call back is the name of a js function in client which then will feeded by the output json | |
* render(:update) do |page| #renders the block as an rjs tempalte | |
page[:cart].replace_html :partial => 'cart', :object => @cart | |
page[:cart].visual_effect :blind_down if @cart.total_items == 1 | |
end | |
% there is always 3 optional parameters: :status, :layout, :content_type | |
. the layout says the result should be wrapped out in a layout, like the default application.html.erb | |
** render_to_string, returns a string, no DoubleRenderError :) | |
% Sendin Files and other data | |
* send_data(png_data, :type=>'image/png', :disposition => "inline | attachment") #sends a datastream | |
* send_file | |
%Redirects | |
* redirect_to(:action => ..., options) | |
* redirect_to(:path =>) | |
* redirect_to(:back) | |
* Sessions | |
-> they are easy loaded | |
1- session_store = :cookie_store => default , max 4kb | |
2- session_store = :p_store => stores each session in an individual file in PStore format | |
3- session_store = :active_record_store => stores the data in database, it just stores the row id in the users cookies | |
4- session_store = :drb_store => stores the data on a DRb server, for applications running on several servers | |
5- session_store = :mem_cache_store => distributed object caching system | |
6- session_store = :memory_store => stores every thing in local memory without serialisation. not a good idea | |
7- session_store = :file_store => store in flat files. just strings. pretty useless for rails apps | |
> for small sessions cookies are best solution. for larger ones active record and drb | |
%session Expiry and Cleanup | |
-> in serverside sessions they need to get cleaned up after user logs out or in a certain amount of deactivity time | |
-> the best way is to clean the data on server, and not to expire the cookie on client | |
* in active records sessions updated_at is usefull: delete from sessions where now() - updated_at > 3600; | |
%Flash: Communicating between actions | |
-> it is stored in session | |
* flash => will be passed to the next action using session and then destroyed | |
* flash.now => will be used in the current request only | |
* flash.keep(...) => will preserve the current or chosen variables to the next request | |
%Filters | |
-> before, after, around | |
-> naming convention: private method, *_filter | |
-> they can get a block or a class also, for more complicated cases | |
* :except, :only | |
filter is_logedin, :except => [login] # or :only... | |
-> prepend_before_filter, prepend_after_filter would prepend instead of append the filter to the filter chain | |
-> arround filters wrap the execution of the action using a yield (before and after) | |
%%Filter Inheritance | |
* skip_filter to not run a filter which is defined in the parent class | |
#--- ACTION VIEW ---# | |
#The template environment | |
* All instance variables of the controller | |
* flash, headears, logger, params, request, responce, session -> normally we use them just for debugging | |
* controller => the current controller object. these allows to call the controller methods | |
* base_path => the path to the base directory of the templates | |
%template types | |
* builder for xml | |
* erb for plain dynamic content with ruby | |
* rjs for js | |
# Generating Forms | |
form_for(:model) do |form| | |
form.label :name | |
form.text_field :name, :placeholder => "enter your name here ..." | |
form.label :color | |
form.radio_button :color, "red" | |
form.label :red | |
form.radio_button :color, "yellow" | |
form.label :yellow | |
form.radio_button :color, "green" | |
form.label :green | |
form.label "condiment" | |
form.check_box :ketchup | |
form.label :ketchup | |
form.check_box :mustard | |
form.label :mustard | |
form.select :priority, (1..10) | |
form.select("post", "category", Post::CATEGORIES, {:include_blank => true}) # => very flexible, other ways: http://api.rubyonrails.org/classes/ActionView/Helpers/FormOptionsHelper.html | |
form.date_select :start #=> very reach, e.g. distance_of_time_in_words_to_now, http://api.rubyonrails.org/classes/ActionView/Helpers/DateHelper.html | |
form.time_select :alarm | |
form. | |
* search_field | |
* telephone_field | |
* url_field | |
* email_field | |
* number_field | |
* range_field | |
* hidden_field | |
* password_field | |
... http://edgeguides.rubyonrails.org/form_helpers.html | |
-> use placeholder as above | |
# Processing Forms | |
-> POST: user[name]=rrr will result in a hash user={:name => "rrr"} | |
user.update_attributes(params[:user]) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment