rails 3 beginner to builder 2011 week 7

40
July, 2011 Beginner to Builder Week 7 Sunday, July 31, 11

Upload: richard-schneeman

Post on 10-May-2015

6.119 views

Category:

Education


1 download

DESCRIPTION

This is the 7th of 8 presentations given at University of Texas during my Beginner to Builder Rails 3 Class. For more info and the whole series including video presentations at my blog:http://schneems.com/tagged/Rails-3-beginner-to-builder-2011

TRANSCRIPT

Page 1: Rails 3 Beginner to Builder 2011 Week 7

July, 2011

Beginner to BuilderWeek 7

Sunday, July 31, 11

Page 2: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Rails - Week 7• SQL Crash Course

• where & find

• method_missing

• scopes and class methods

• Pagination

• full text search

• Rake vs. Script/Runner

Sunday, July 31, 11

Page 3: Rails 3 Beginner to Builder 2011 Week 7

• Structured Query Language

• Used to manage data in RDBMS (relational database management system)

• Active Record hides our SQL

@Schneems

SQL

User.where(:username => "foo").to_sql

=> SELECT "users".*

FROM "users" WHERE

"users"."username" = 'foo'

Sunday, July 31, 11

Page 4: Rails 3 Beginner to Builder 2011 Week 7

• find by uniqe id, or ids

• find_by_#{:column_name}

@Schneems

Find

User.find(1)

User.find(1,2,3)

User.find_by_username('schneems')

Sunday, July 31, 11

Page 5: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Method Missing

User.foo_foo

NoMethodError: undefined method `foo_foo' for #<Class:

0x105187be8>

Sunday, July 31, 11

Page 6: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Method Missingclass User

def self.method_missing(method_name, *args, &block)

puts "You just called #{method_name}"

end

end

User.foo_foo

>> "You just called foo_foo"

Sunday, July 31, 11

Page 7: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Method Missingclass User < ActiveRecord::Base

def self.method_missing(method_name, *args, &blk)

if method_name.to_s =~ /^foo_foo_find_by_.*/

column = method_name.to_s.gsub("foo_foo_find_by_", "")

User.where(column.to_sym => args.first)

else

super

end

end

end

User.foo_foo_find_by_username("schneems")

Sunday, July 31, 11

Page 8: Rails 3 Beginner to Builder 2011 Week 7

• Active Record’s Query API

@Schneems

Active Record

find

where (:conditions)

includes (:include)

group

order

limit

offset

joins

having

http://m.onkey.org/active-record-query-interface

Sunday, July 31, 11

Page 9: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Order & Offset# Order# defaults to ascending

User.order(:created_at).first

#<User id: 1, ...

User.order('created_at DESC').first

#<User id: 55, ...

# Offset

User.order(:created_at).offset(1).first

#<User id: 2, ...

User.order(:created_at).offset(2).first

#<User id: 3, ...

Sunday, July 31, 11

Page 10: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Limit & Count

# Limit

User.limit(3).all

[ #<User ... >, #<User ... >, #<User ... > ]

# Count

User.count

=> 55

Sunday, July 31, 11

Page 11: Rails 3 Beginner to Builder 2011 Week 7

• Group

@Schneems

Group

# Group

User.group(:hometown).count(:hometown)

#<OrderedHash {

"Austin, Texas"=>28,

"Alexandria, MN"=>1,

"Warsaw, Poland"=>1,

# ...

}

Sunday, July 31, 11

Page 12: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Joins

# Joins

BlogPost.joins(:user).where(:user_id => 2).first

=> #<BlogPost id: 13023, name: The best of times>

Sunday, July 31, 11

Page 13: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Include

# Include pre-fetches data

User.where(:id => 3).includes(:posts => :comments)

user = User.find(3)

post = user.posts.all.first

post.comments

Sunday, July 31, 11

Page 14: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Having

# having

User.group(:hometown).having("COUNT(hometown) > 22").count

#<OrderedHash

{"Austin, Texas"=>28,

"Austin, TX"=>102,

"San Francisco, CA"=>92,

"Dallas, TX"=>56}>

Sunday, July 31, 11

Page 15: Rails 3 Beginner to Builder 2011 Week 7

• can take raw sql statement

@Schneems

Where

User.where("username = foo").to_sql

=> "SELECT \"users\".* FROM \"users\"

WHERE (username = foo)"

Sunday, July 31, 11

Page 16: Rails 3 Beginner to Builder 2011 Week 7

• Like

@Schneems

Where

# 'Like' does a search using % as wildcard

User.where("username like '%foo%'")

# will match '...zfoo', 'fooz...', etc.

Sunday, July 31, 11

Page 17: Rails 3 Beginner to Builder 2011 Week 7

• Null

@Schneems

Where

# 'NULL' checks blank entries

User.where("username IS NULL")

# 'NOT' negates query

User.where("username IS NOT NULL")

Sunday, July 31, 11

Page 18: Rails 3 Beginner to Builder 2011 Week 7

• Equality Operators

@Schneems

Where

# '<>' is SQL not equal

User.where("username <> 'foo'")

# "greater than"

User.where("popularity > 5")

# "less than"

User.where("popularity < 5")

Sunday, July 31, 11

Page 19: Rails 3 Beginner to Builder 2011 Week 7

• SQL Functions

@Schneems

Where

# DATE() is a SQL function

User.where("DATE(created_at) > DATE('#{5.days.ago}')")

# Other Functions:

# AVG, SUM, COUNT, MIN, MAX

Sunday, July 31, 11

Page 20: Rails 3 Beginner to Builder 2011 Week 7

• (?) passes data into SQL safely

@Schneems

Where

User.where("DATE(created_at) > DATE(?)", 5.days.ago)

Sunday, July 31, 11

Page 21: Rails 3 Beginner to Builder 2011 Week 7

• SQL injection attacks

@Schneems

SQL Security

name = "'' or 1 DROP TABLE USERS"

# Bad

User.where("name = #{name}")

# Good

User.where("name = ?", name)

User.where(:name => name)

Sunday, July 31, 11

Page 22: Rails 3 Beginner to Builder 2011 Week 7

• Lazy Loading

@Schneems

ActiveRecord

# stores Query, doesn’t hit the DB

cars = Car.where(:colour => 'black')

# .each Fires "select * from cars where ..."

cars.each {|c| puts c.name }

# Now We can Chain

Item.limit(10).order('created_at DESC')

Sunday, July 31, 11

Page 23: Rails 3 Beginner to Builder 2011 Week 7

• Re-use your queries

@Schneems

Scopes

class Product < ActiveRecord::Base

scope :discontinued, where(:discontinued => true)

scope :cheap, where("price < 5")

end

Product.discontinued.first

Product.discontinued.cheap.first

Sunday, July 31, 11

Page 24: Rails 3 Beginner to Builder 2011 Week 7

• Re-use your queries

@Schneems

Scopes

class Product < ActiveRecord::Base

scope :cheaper_than,

lambda { |price| where("price < ?", price) }

end

Product.cheaper_than(5).first

Sunday, July 31, 11

Page 25: Rails 3 Beginner to Builder 2011 Week 7

• Re-use your queries

• Better than scopes

@Schneems

Class Methods

class Product < ActiveRecord::Base

def self.cheaper_than(price)

where("price < ?", price)

end

end

Product.cheaper_than(5).first

Product.cheaper_than(5).order.limit(5).first

Sunday, July 31, 11

Page 26: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Rake# /lib/tasks/users.rake

namespace :users do

desc "Create dummy users"

task :populate => :environment do

5.times do

User.build(:name => Faker.first_name)

end

end

end

# execute with

> rake users:populate

Sunday, July 31, 11

Page 27: Rails 3 Beginner to Builder 2011 Week 7

• Can be used independently from Rails

@Schneems

Rake

# /lib/tasks/foo.rake

namespace :foo do

desc "foo bars"

task :bar do

# ...

end

end

Sunday, July 31, 11

Page 28: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Script/Runner

# /lib/user_populate.rb

5.times do

User.build(:name => Faker.first_name)

end

# execute with

> script/runner /lib/user_populate.rb

Sunday, July 31, 11

Page 29: Rails 3 Beginner to Builder 2011 Week 7

• Versatile

• Useful outside of rails

• favored over script/runner

@Schneems

Rake Wins

Sunday, July 31, 11

Page 30: Rails 3 Beginner to Builder 2011 Week 7

• Split up large data into chunks

• will_paginate gem

@Schneems

Pagination

post = BlogPost.paginate :page => params[:page], :per_page => 20

post.total_count # => 200

post.count # => 20

Sunday, July 31, 11

Page 31: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Full Text Search

# SQL Like

BlogPost.where("title like '%?%", params[:title])

# slow

# doesn't deal with

# punctuation

# pluralization

# etc.

Sunday, July 31, 11

Page 32: Rails 3 Beginner to Builder 2011 Week 7

• Open Source Search Server

• Based on Lucene

• Fast

• Feature rich

• Easily Accessed ruby API wrappers

@Schneems

SOLR

Sunday, July 31, 11

Page 33: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Sunspot GEMclass BlogPost < ActiveRecord::Base

searchable do

text :title, :body

text :comments do

comments.map { |comment| comment.body }

end

time :published_at

string :sort_title do

title.downcase.gsub(/^(an?|the)/, '')

end

end

end

Sunday, July 31, 11

Page 34: Rails 3 Beginner to Builder 2011 Week 7

• Paginated

@Schneems

Sunspot GEM

BlogPost.search do

fulltext 'best pizza'

with(:published_at).less_than Time.now

order_by :published_at, :desc

paginate :page => 2, :per_page => 15

facet :category_ids, :author_id

end

Sunday, July 31, 11

Page 35: Rails 3 Beginner to Builder 2011 Week 7

• Open Source

• Full text search server

@Schneems

Sphinx

Sunday, July 31, 11

Page 36: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Thinking Sphinx GEMclass Article < ActiveRecord::Base

define_index do

# fields

indexes subject, :sortable => true

indexes content

indexes author.name, :as => :author, :sortable => true

# attributes

has author_id, created_at, updated_at

end

end

Sunday, July 31, 11

Page 37: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Thinking Sphinx GEM

Article.search "topical issue"

Article.search "something",

:order => :created_at,

:sort_mode => :desc

Sunday, July 31, 11

Page 38: Rails 3 Beginner to Builder 2011 Week 7

• Flying Sphinx add-on in heroku

@Schneems

Sphinx

Sunday, July 31, 11

Page 39: Rails 3 Beginner to Builder 2011 Week 7

• Index Tank

@Schneems

3rd Parties/Black Box# Connect to Service

api = IndexTank::Client.new "<YOUR API URL HERE>"

index = api.indexes "<YOUR INDEX NAME>"

# add documents

docid = "<YOUR DOCUMENT ID>"

text = "<THE TEXTUAL CONTENT>"

index.document(docid).add({ :text => text })

# search documents

results = index.search "foo"

Sunday, July 31, 11

Page 40: Rails 3 Beginner to Builder 2011 Week 7

@Schneems

Questions?

http://guides.rubyonrails.orghttp://stackoverflow.com

http://peepcode.com

Sunday, July 31, 11