Skip to content

Instantly share code, notes, and snippets.

@xdite
Created July 14, 2012 05:11

Revisions

  1. xdite revised this gist Jul 14, 2012. 2 changed files with 1206 additions and 238 deletions.
    238 changes: 0 additions & 238 deletions 42-things-1.md
    Original file line number Diff line number Diff line change
    @@ -1,238 +0,0 @@
    ### 1. Get You a Hug, Every Friday

    FridayHug.com <http://fridayhug.com>

    ### 2. Run From a Single File

    The Smallest Rails App <http://thesmallestrailsapp.com>

    ``` ruby
    %w(action_controller/railtie coderay).each &method(:require)

    run TheSmallestRailsApp ||= Class.new(Rails::Application) {
    config.secret_token = routes.append { root to: 'hello#world' }.inspect
    initialize!
    }

    class HelloController < ActionController::Base
    def world
    render inline: %Q{
    <!DOCTYPE html>
    <title>The Smallest Rails App</title>
    <h3>I am the smallest rails app!</h3>
    <p>Here is my source code:</p>
    #{CodeRay.scan_file(__FILE__, :ruby).div(line_numbers: :table)}
    <a href="https://github.com/artemave/thesmallestrailsapp.com">Make me smaller</a>
    }
    end
    end
    ```

    ### 3. Remind You of Things

    ``` ruby
    class UsersController < ApplicationController
    # TODO: Make it possible to create new users.
    end
    ```

    ``` ruby
    class User < ActiveRecord::Base
    # FIXME: Should token really be accessible?
    attr_accessible :bio, :email, :name, token
    end
    ```

    ``` ruby
    <% OPTIMIZE: Paginate this listing. %>
    <%= render Article.all %>
    ```

    #### rake notes

    ```
    $rake notes
    app/controllers/users_controller.rb
    * [ 2][TODO] Make it possible to create new users.
    app/modles/user.rb:
    * [ 2][FIXME] Should token really be accessible?
    app/views/articles/index.htmk.erb:
    * [ 2][OPTIMIZE] Paginate this listing.
    ```

    #### rake notes:todo
    ```
    $rake notes:todo
    app/controllers/users_controller.rb
    * [ 2] Make it possible to create new users.
    ```

    #### rake notes:fixme

    ```
    $rake notes:fixme
    app/controllers/users_controller.rb
    * [ 2] Should token really be accessible?
    ```

    #### rake notes:custom ANNOTATION=JEG2

    ``` ruby
    class Article M ActiveRecord::Base
    belongs_to :user
    attr_accessible :body, :subject
    # JEG2: Add that code from your blog here.
    end
    ```

    ```
    $ rake notes:custom ANNOTATION=JEG2
    app/modles/article.rb
    * [ 4] Add that code from your blog here.
    ```
    #### TextMate Bundles

    * Bundles > TODO > Show TODO List

    ### 4. Sandbox Your Console

    #### rails r

    ```
    $ rails r 'p [Article, Comment, User].map(&:count)'
    [0,0,0]
    ```

    #### rails c --sanbox

    rolls back changes

    ```
    $ rails c --sandbox
    Loading development environment in sandbox (Rails 3.2.3)
    Any modifications you make will be rolled back on exit
    >> jeg2 = User.create!(name: "Jame Edward Gray II")
    => #<User id: 1, name: "Jame Edward Gray II", …>
    >> article = Article.new(subject: "First Post").tap { |a| a.user = jeg2; a.save! }
    => #<Article id: 1, user_id: 1, ubject: "First Post", …>
    >> Comment.new(body: "I need to add this.").tap { |c| c.user, c.article = jeg2, article' c.save! }
    => #<Comment id: 1, user_id: 1, article_id: 1, body: "I need to add this.", …>
    >> [Article, Comment, User].map(&:count)
    => [1, 1, 1]
    >> exit
    $ rails r 'p [Article, Comment, User].map(&:count)'
    [0,0,0]
    ```
    ### 5. Run Helper Methods in the Console

    ```
    $ rails c
    Loading development environment ( Rails 3.2.3)
    >> helper.number_to_currency(100)
    >> "$100.00"
    >> helper.time_ago_in_words(3.days.ago)
    => "3 days"
    ```

    ### 6. Use Non-WEBriock Servers in Development

    ``` ruby
    source 'https://rubygems.org'
    #
    group :developemnt do
    gem "thin"
    end
    ```

    ```
    $ rails s thin
    => Booting Thin
    => Rails 3.2.3 application starting in development on http://0.0.0.0:3000
    => Call with -d to detach
    >> Thin web server (v1.3.1 codename Triple Espresso)
    >> Maximum connections set to 1024
    >> Listening on 0.0.0.0:3000, CTRL+C to stop
    ```
    ### 7. Allow You to Tap into its Configuration

    * require Railtie, with config.custom in Railtie

    ``` ruby
    # lib/custom/railtie.rb
    module Custom
    class Railtie < Rails::Railtie
    config.custom = ActiveSupport::OrderedOptions.new
    end
    end
    ```

    * You can configure plugins the same way you configure Rails

    ``` ruby
    # config/application.rb
    #

    require_relavtive "../lib/custom/railtie"
    module Blog
    class Application < Rails::Application
    #
    config.custom.setting = 42
    end
    end
    ```

    ### 8. Keep You Entertained

    Ruby Dramas <http://rubydramas.com>

    ### 9. Understand Shorthand Migrations

    ```
    $ rails g resources user name:string email:string token:string bio:text
    ```

    * Default is string, can add limits

    ```
    $ rails g resources user name email token:string{6} bio:text
    ```

    ``` ruby
    class CreateUsers < ActiveRecord::Migration
    def change
    create_table :users do |t|
    t.string :name
    t.string :email
    t.string :token, :limit => 6
    t.text :bio

    t.timestamps
    end
    end
    end
    ```

    ### 10. Add Indexes to Migrations

    ```
    $ rails g resource user name:index email:uniq token:string{6} bio:text
    ```

    ``` ruby
    class CreateUsers < ActiveRecord::Migration
    def change
    create_table :users do |t|
    t.string :name
    t.string :email
    t.string :token, :limit => 6
    t.text :bio

    t.timestamps
    end
    add_index :users, :name
    add_index :users, :email, :unique => true
    end
    end
    ```
    1,206 changes: 1,206 additions & 0 deletions 42-things.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,1206 @@
    ### 1. Get You a Hug, Every Friday

    FridayHug.com <http://fridayhug.com>

    ### 2. Run From a Single File

    The Smallest Rails App <http://thesmallestrailsapp.com>

    ``` ruby
    %w(action_controller/railtie coderay).each &method(:require)

    run TheSmallestRailsApp ||= Class.new(Rails::Application) {
    config.secret_token = routes.append { root to: 'hello#world' }.inspect
    initialize!
    }

    class HelloController < ActionController::Base
    def world
    render inline: %Q{
    <!DOCTYPE html>
    <title>The Smallest Rails App</title>
    <h3>I am the smallest rails app!</h3>
    <p>Here is my source code:</p>
    #{CodeRay.scan_file(__FILE__, :ruby).div(line_numbers: :table)}
    <a href="https://github.com/artemave/thesmallestrailsapp.com">Make me smaller</a>
    }
    end
    end
    ```

    ### 3. Remind You of Things

    ``` ruby
    class UsersController < ApplicationController
    # TODO: Make it possible to create new users.
    end
    ```

    ``` ruby
    class User < ActiveRecord::Base
    # FIXME: Should token really be accessible?
    attr_accessible :bio, :email, :name, token
    end
    ```

    ``` ruby
    <% OPTIMIZE: Paginate this listing. %>
    <%= render Article.all %>
    ```

    #### rake notes

    ```
    $rake notes
    app/controllers/users_controller.rb
    * [ 2][TODO] Make it possible to create new users.
    app/modles/user.rb:
    * [ 2][FIXME] Should token really be accessible?
    app/views/articles/index.htmk.erb:
    * [ 2][OPTIMIZE] Paginate this listing.
    ```

    #### rake notes:todo
    ```
    $rake notes:todo
    app/controllers/users_controller.rb
    * [ 2] Make it possible to create new users.
    ```

    #### rake notes:fixme

    ```
    $rake notes:fixme
    app/controllers/users_controller.rb
    * [ 2] Should token really be accessible?
    ```

    #### rake notes:custom ANNOTATION=JEG2

    ``` ruby
    class Article M ActiveRecord::Base
    belongs_to :user
    attr_accessible :body, :subject
    # JEG2: Add that code from your blog here.
    end
    ```

    ```
    $ rake notes:custom ANNOTATION=JEG2
    app/modles/article.rb
    * [ 4] Add that code from your blog here.
    ```
    #### TextMate Bundles

    * Bundles > TODO > Show TODO List

    ### 4. Sandbox Your Console

    #### rails r

    ```
    $ rails r 'p [Article, Comment, User].map(&:count)'
    [0,0,0]
    ```

    #### rails c --sanbox

    rolls back changes

    ```
    $ rails c --sandbox
    Loading development environment in sandbox (Rails 3.2.3)
    Any modifications you make will be rolled back on exit
    >> jeg2 = User.create!(name: "Jame Edward Gray II")
    => #<User id: 1, name: "Jame Edward Gray II", …>
    >> article = Article.new(subject: "First Post").tap { |a| a.user = jeg2; a.save! }
    => #<Article id: 1, user_id: 1, ubject: "First Post", …>
    >> Comment.new(body: "I need to add this.").tap { |c| c.user, c.article = jeg2, article' c.save! }
    => #<Comment id: 1, user_id: 1, article_id: 1, body: "I need to add this.", …>
    >> [Article, Comment, User].map(&:count)
    => [1, 1, 1]
    >> exit
    $ rails r 'p [Article, Comment, User].map(&:count)'
    [0,0,0]
    ```
    ### 5. Run Helper Methods in the Console

    ```
    $ rails c
    Loading development environment ( Rails 3.2.3)
    >> helper.number_to_currency(100)
    >> "$100.00"
    >> helper.time_ago_in_words(3.days.ago)
    => "3 days"
    ```

    ### 6. Use Non-WEBriock Servers in Development

    ``` ruby
    source 'https://rubygems.org'
    #
    group :developemnt do
    gem "thin"
    end
    ```

    ```
    $ rails s thin
    => Booting Thin
    => Rails 3.2.3 application starting in development on http://0.0.0.0:3000
    => Call with -d to detach
    >> Thin web server (v1.3.1 codename Triple Espresso)
    >> Maximum connections set to 1024
    >> Listening on 0.0.0.0:3000, CTRL+C to stop
    ```
    ### 7. Allow You to Tap into its Configuration

    * require Railtie, with config.custom in Railtie

    ``` ruby
    # lib/custom/railtie.rb
    module Custom
    class Railtie < Rails::Railtie
    config.custom = ActiveSupport::OrderedOptions.new
    end
    end
    ```

    * You can configure plugins the same way you configure Rails

    ``` ruby
    # config/application.rb
    #

    require_relavtive "../lib/custom/railtie"
    module Blog
    class Application < Rails::Application
    #
    config.custom.setting = 42
    end
    end
    ```

    ### 8. Keep You Entertained

    Ruby Dramas <http://rubydramas.com>

    ### 9. Understand Shorthand Migrations

    ```
    $ rails g resources user name:string email:string token:string bio:text
    ```

    * Default is string, can add limits

    ```
    $ rails g resources user name email token:string{6} bio:text
    ```

    ``` ruby
    class CreateUsers < ActiveRecord::Migration
    def change
    create_table :users do |t|
    t.string :name
    t.string :email
    t.string :token, :limit => 6
    t.text :bio

    t.timestamps
    end
    end
    end
    ```

    ### 10. Add Indexes to Migrations

    ```
    $ rails g resource user name:index email:uniq token:string{6} bio:text
    ```

    ``` ruby
    class CreateUsers < ActiveRecord::Migration
    def change
    create_table :users do |t|
    t.string :name
    t.string :email
    t.string :token, :limit => 6
    t.text :bio

    t.timestamps
    end
    add_index :users, :name
    add_index :users, :email, :unique => true
    end
    end
    ```

    ### 11. Add Associations to a Migration

    ```
    $ rails g resouce article user:references subject body:text
    ```

    ``` ruby
    class CreateArticles < ActiveRecord::Migration
    def change
    create _table :articles do |t|
    t.references :user
    t.string :subject
    t.text :body

    t.timestamps
    end

    add_index :articles, :user_id
    end
    end
    ```

    ``` ruby
    class Article < ActiveRecord::Base
    belongs_to :user
    attr_accessible :body, :subject
    end
    ```


    ```
    $ rails g resource comment user:belongs_to article:belongs_to body:text
    ```


    ### 12. Show You the Status of the Database

    ```
    $ rake db:migrate:status
    database: db/development.sqlite3
    Status Migration ID MigrationName
    ---------------------------------------
    up 20120414155612 Create users
    up 20120414160528 Create articles
    down 20120414161355 Create comments
    ```

    ### 13. Import Your CSV Data

    ```
    Name,Email
    James,james@example.com
    Dana,dana@example.com
    Summer,summer@example.com
    ```

    ``` ruby
    require "csv"

    namespace :users do
    desc "Import users from a CSV file"
    task :import => :environment do
    path = ENV.fetch("CSV_FILE"){
    File.join(File.dirname(__FILE__), *%w[.. .. db data users.csv])
    }
    CSV.foreach(path, headers: true, header_converters: :symbol) do |row|
    User.create(row.hash)
    end
    end
    end
    ```

    ### 14. Store CSV in Your Database

    ``` ruby
    class Article < ActiveRecord::Base
    require "csv"

    module CSVSerializer
    module_founction
    def load(field) field.to_s.parse_csv end
    def dump(object) Array(object).to_csv end
    end

    serialize :categories, CSVSerializer

    #

    attr_accessible :body, :subject, :categories
    end
    ```
    ```
    $ rails c
    Loading development environment (Rails 3.2.3)
    >> Article.create!(:subject: "JEG2's Rails Hacks", categories: [" Rails", "Gray, James", "hacks"])
    => #<Article id 1, …>
    >> Aticle.last.categories
    => ["Rails", "Gray, Jazmes", "hacks"]
    >> exit
    $ sqlite3 db/development.sqlite3 'SELECT categories FROM aricles ORDER BY created_at DESC LIMIT 1'
    -- Loading resources from Users/james/.sqliterc categories --
    Raiols,"Gray, James",hacks
    ```

    ### 15. "Pluck" Fields Out of Your Database

    ```
    $ rails c
    Loading development environment (Rails 3.2.3)
    >> User.select(:email).map(&:email)
    User Load (0.1ms) SELECT email FROM "users"
    ==> ["james@example.com", "dana@example.com", "summer@example.com"]
    >> User.pluck(:email)
    (0.2ms) SELECT email FROM "users"
    ==> ["james@example.com", "dana@example.com", "summer@example.com"]
    >> User.uniq.plurk(:email)
    (0.2ms) SELECT DISTINCT email FROM "users"
    ==> ["james@example.com", "dana@example.com", "summer@example.com"]
    ```

    ### 16. Count Records in Groups

    ```
    $ rails g resource event article:belongs_to trigger
    ```

    ```
    $ rails c
    Loading development environment (Rails 3.2.3)
    >> article = Article.last
    => #<Atricle id: 1, …>
    >> { edit: 3, view: 10}.each do |trigger, count|
    ?> count.times do
    ?> Event.new(:trigger: trigger).tap | |e| e.article = article; e.save! }
    >> end
    >> end
    => {:edit => 3, :view => 10}
    >> Event.count
    ==> 13
    >> Event.group(:trigger).count
    >> {"edit"=> 3, "view"=> 10}
    ```

    ### 17. Allow You to Override Associations

    ``` ruby
    class Car ActiveRecord::Base
    belongs_to :owner
    belongs_to :previous_owner, class_name: "Owner"

    def owner=(new_owner)
    self.previous_owner = owner
    super
    end
    end
    ```

    ### 18. Instantiate Records Without a Database

    ```
    $ rails c
    Loading development environment (Rails 3.2.3)
    >> User.find(1)
    ==> #<User id: 1, name: "James", email: "james@example.com", …>
    >> jeg2 = User.instantiate("id" => 1, "email" => "james@example.com")
    => #<User id: 1, email: "james@example.com">
    >> jeg2.name = "James Edwward Gray II"
    => "James Edward Gray II"
    >> jeg.save!
    >> true
    >> User.find(1)
    => #<User id: 1, nmame: "James Edward Gray II", email: "james@example.com", …>
    ```

    ### 19.

    Use Limitless String in PostgreSQL

    ```
    $ rails g resource user bio
    ```

    ``` ruby
    #
    module PsqlApp
    class Application < Rails:: Application
    #

    # Switch to limitless string
    initializer "postgresql.no_default_string_limit" do
    ActiveSupport.on_load(:active_record) do
    adapter = ActiveRecord::ConnectionAdapters::PostgreSQLAdapter
    adapter::NATIVE_DATABASE_TYPES[:string].delete(:limit)
    end
    end
    end
    end
    ```

    ```
    $ rails g resource user bio
    ```

    ```
    $ rails c
    Loading development environment (Rails 3.2.3)
    >> very_long_bbio = "X" * 10_000; :set
    => :set
    >> User.create!(bio: very_loing_bio)
    >> #< User id: 1, bio:
    "XXXXXXXXXXXXXXXX….", created_at: "2012-04-14 23:02:08", updated_at: "2012-04-14 23:02:08">
    >> User.last.bio.size
    >> 10000
    ```

    ### 20. Use Full Text Search in PostgreSQL

    ```
    $ rails g resource article subject body:text
    ```

    ``` ruby
    class CreateArticles < ActiveRecord::Migration
    def change
    create_table :articles do |t|
    t.string :subject
    t.text :body
    t.column :search, "tsvector"

    t.timestamps
    end

    execute <<- END_SQL
    CREATE INDEX articles_search_index ON articles USING gin(search);

    CREATE TRIGGER articles_search_update
    BEFORE INSERT OR UPDATE ON articles
    FOR EACH ROW EXECUTE PROCEDURE
    tsvector_update_trigger( search, 'pg_catalog.english', subhect,body );

    END_SQL
    end
    end
    ```


    ``` ruby
    class Article < ActiveRecord::Base
    attr_accessible :body, :subject

    def self.search(query)
    sql = sanitize_sql_array(["plainto_tsquery('english', ? )", query])
    where(
    "seearch @@ #{sql}"
    ).order(
    "ts_rank_cd(search, #{sql}) DESC"
    )
    end
    end
    ```

    ```
    $ rails c
    Loading development environment (Rails 3.2.3)
    >> Article.create!(subject: "Full Text Search")
    => #<Article id 1, …>
    >> Article.create!(body: "A stemmed search.")
    => #<Article id 2, …>
    >> Article.create!(body: "You won't find me!")
    > #<Article id 3, …>
    >> Article.search("search").map { |a| a.subject || a.body }
    => ["Full Text Search", "A stemmed search."]
    >> Article.search("stemming").map { |a| a.subject || a.body }
    => "A stemmed search."
    ```

    ### 21. Different a Database for Each User

    ``` ruby
    def connect_to_user_database(name)
    config = ActiveRecord::Base.configurations["development"].merge("database" => "db/#{name}.sqlite3")
    ActiveRecord::Base.establish_connection(config)
    end
    ```


    ``` ruby
    namespace :db do
    desc "Add a new user database"
    task :add => %w[environment load_config] do
    name = ENV.fetch("DB_NAME") { fail "DB_NAME is required"}
    connect_to_user_database(name)
    ActiveRecord::Base.connection
    end
    end

    namespace :migrate do
    desc "Migrate all user databases"
    task :all => %w[environment load_config] do
    ActiveRecord::Migration.vervbose = ENV.fetech("VERBOSE", "true") == "true"
    Dir.glob("db/*.sqlite3") do |file|
    next if file == "db/test.sqlite3"
    connect_to_user_database(File.basename(file, ".sqlite3"))
    ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] && ENV["VERSION"].to_i ) do |migration|
    ENV["SCOPE"].blank? || (ENV["SCOPE"] == migration.scope)
    end
    end
    end
    end
    ```

    ```
    $ rails g resource user name
    $ rake db:add DB_NAME=ruby_rogues
    $ rake db:add DB_NAME=grays
    $ rake db:migrate:all
    == CreateUsers: migration ==============
    -- create_table(:users)
    -> 0.008s
    == CreateUsers: migrated (0.0008s) ==============
    == CreateUsers: migration ==============
    -- create_table(:users)
    -> 0.007s
    == CreateUsers: migrated (0.0008s) ==============
    ```


    ```
    $ rails c
    >> connect_to_user_database("ruby_rogues")
    => #<ActiveRecord::ConnectionAdapters::ConnectionPool...>
    >> User.create!(name: "Chuck")
    => #<User id: 1, name: "Chuck", ...>
    >> User.create!(name: "Josh")
    => #<User id: 2, name: "Josh", ...>
    >> User.create!(name: "Avdi")
    => #<User id: 3, name: "Avdi", ...>
    ...
    >> connect_to_user_database("grays")
    => #<ActiveRecord::ConnectionAdapters::ConnectionPool...>
    >> User.create!(name: "James")
    => #<User id: 1, name: "James", ...>
    >> User.create!(name: "Dana")
    => #<User id: 2, name: "Dana", ...>
    >> User.create!(name: "Summer")
    => #<User id: 3, name: "Summer", ...>
    >>
    ```


    ``` ruby
    class ApplicationController < ActionController::Base
    protect_from_forgrey

    before_filter :connect_to_database

    private

    def connect_to_database
    connect_to_user_database(request.subdomains.first)
    end
    end
    ```

    ### 22. Fefine Your Fashion Sense

    * <http://www.flickr.com/photos/oreillyconf/5735037920/>
    * <http://www.flickr.com/photos/oreillyconf/5735038376/>
    * <http://www.flickr.com/photos/aaronp/4609780419>

    ### 23. Write Files Atomically

    ``` ruby
    class Comment < ActiveRecordd::Base
    # ...

    Q_DIR = (Rails.root + "comment_queue").tap(&:mkpath)
    after_save :queue_comment
    def queue_comment
    File.atomic_write(Q_DIR + "#{id}.txt") do |f|
    f.puts "Article: #{aticle.subject}"
    f.puts "User: #{user.name}"
    f.puts body
    end
    end
    end
    ```


    ```
    $ ls comment_queue
    ls: comment_queue: No such file or directory
    $ rails r 'Comment.new(body: "Queue me.").tap { |c| c.article, c.user = Article.first, User.first; c.save!}'
    $ ls comment_queue
    1.text
    $ cat comment_queue/1.txt
    Article.: JEG2's Rails Hacks
    User: James Edward Gray II
    Queue me.
    ```

    ### 24. Merge Nested Hashes

    ```
    $ rails c
    Loading development environment (Rails 3.2.3)
    >> {nested: {one :1}}.merge(nested: {two: 2})
    => {:nestd => {:two=>2}}
    >> {nested: {one :1}}.deep_merge(nested: {two: 2})
    => {:nestd => {:one=>1, :two=>2}}
    ### 25. Remove Speicific Keys From a Hash
    ```
    $ rails c
    Loading development environment (Rails 3.2.3)
    >> params = {controller: "home", action: "index", from: "Google"}
    => {:controller => "home", :action => "index", :from => "Google"}
    >> params.except(:controller, :action)
    => {:from => "Google"}
    ## 26. Add Defaults to Hash

    ```
    $ rails c
    Loading development environment (Rails 3.2.3)
    >> {required: true}.merge(optional: true)
    => {:required => true, :optional => true}
    >> {required: true}.reverese_merge(optional: true)
    => {:optional => true, :required => true}
    >> {required: true, optional: false}.merge(optional: true)
    => {:required => true, :optional => true}
    >> {required: true, optional: false}.reverse_merge(optional: true)
    => {:optional => false, :required => true}
    ```

    ### 27. Answer Questions About Strings

    ```
    $ rails g migration add_status_to_articles status
    ```

    ``` ruby
    class AddStatusToArticles < ActiveRecord::Migration
    def change
    add_column :articles, :status, :string, default => "Draft", null: false
    end
    end
    ```

    ```
    $ rails c
    Loading development environment (Rails 3.2.3)
    >> env = Rails.env
    => "development"
    >> env.development?
    => true
    >> env.test?
    => false
    >> "magic".inquiry.magic?
    => true
    >> article = Article.first
    => #<Article id: 1, ..., status: "Draft">
    >> article.draft?
    => true
    >> article.published?
    => false
    ```

    ``` ruby
    class Article < ActiveRecord::Base

    # ...

    STATUS = %w[Deaft Published]
    validates_inclusion_of :status, in: STATUS

    def method_mssing(methods, :status, &block)
    if method =~/\A#{STATUS}.map(&:downcase).join("|")}\?\z/
    status.downcase.inquiry.send(method)
    else
    super
    end
    end
    end
    ```

    ### 28. Get you on the cover of a magazine

    * <http://www.rubyinside.com/rubys-popularity-scales-new-heights-19.html>

    ### 29. Get you voted "Hottest Hacker"

    * <http://pageman.multiply.com/links/item/21/David_Heinemeier_Hanssons_Blog>

    * <http://torrentfreak.com/richard-stallman-opts-to-disobey-anti-piracy-law-110610/>


    ### 30. Hide Comments From Your Users

    ``` html
    <!-- HTML comments stay in the rendered content -->
    <% ERb comments do not %>
    <h1>Home Page</h1>
    ```

    ``` html
    <body>
    <!-- HTML comments stay in the rendered content -->
    <h1>Home Page</h1>
    </body>
    ```


    ### 31. Understand a Shoter ERb syntax

    ``` ruby

    # ...

    module Blog
    class Application < Rails::Application
    # ...

    # Broken: config.action_view.erb_trim_mode = '%'

    ActiveView::Template::Handlers::ERB.erb_implementation =
    Class.new(ActiveVieew::Template::Handlers::Erubis) do
    include ::Erubis::PercentLineEnhancer
    end
    end

    ```

    ```
    % if current_user.try(:admin?)
    <%= render "edit_links" %>
    %
    ```

    ### 32. Use Blocks to Avoid Assignments in Views

    ``` erb
    <table>
    <% @cart.products.each do |product| %>
    <tr>
    <td> <%= product.name %> </td>
    <td> <%= number_to_currency product.price %> </td>
    </tr>
    <% end %>
    <tr>
    <td> Subtotal </td>
    <td> <%= number_to_currency @cart.total %> </td>
    </tr>
    <tr>
    <td> Tax </td>
    <td> <%= number_to_currency (tax = calculate_tax(@cart.tototal)) %> </td>
    </tr>
    <tr>
    <td> Total </td>
    <td> <%= number_to_currency(@cart.total + tax %> </td>
    </tr>
    </table>
    ```

    =>

    ``` erb
    <table>
    <% @cart.products.each do |product| %>
    <tr>
    <td> <%= product.name %> </td>
    <td> <%= number_to_currency product.price %> </td>
    </tr>
    <% end %>
    <tr>
    <td> Subtotal </td>
    <td> <%= number_to_currency @cart.total %> </td>
    </tr>
    <% calculate_tax @cart.total do |tax| %>
    <tr>
    <td> Tax </td>
    <td> <%= number_to_currency tax) %> </td>
    </tr>
    <tr>
    <td> Total </td>
    <td> <%= number_to_currency(@cart.total + tax %> </td>
    </tr>
    <% end %>
    </table>
    ```


    ``` ruby
    module CartHelper
    def calculat_text(total, user = current_user)
    tax = TaxTable.for(user).calculate(total)
    if block_given?
    yield tax
    else
    tax
    end
    end
    end
    ```

    ### 33. Generate Muliple Tags at Once

    ``` erb
    <h1> Articles </h1>
    <% @articles.each do |article| %>
    <%= content_tag_for(:div, article) do %>
    <h2> <%= article.subject %> </h2>
    <% end 5>
    <% end %>
    ```

    =>


    ``` erb
    <h1> Articles </h1>
    <%= content_tag_for(:div, @articles) do |article| do %>
    <h2> <%= article.subject %> </h2>
    % end %>
    ```

    ### 34. Render Any Object

    ``` ruby
    class Event < ActiveRecord::Base
    # ...

    def to_partial_path
    "events/#{trigger}" # events/edit or events/view
    end
    end

    ```

    ``` erb
    <%= render partial: @events, as: :event %>
    ```

    ### 35. Group Menu Entries

    ``` erb
    <%= select_tag(:grouped_menu, group_options_for_select(
    "Group A" => %w[One Two Three],
    "Group B" => %w[One Two Three],
    ))%>
    ```

    ### 36. Build Forms the Way You Like Them

    ``` ruby

    class LabeledFieldsWithErrors < ActionView::Helpers::FormBuilder
    def errors_for(attribute)
    if (errors = object.errors[attribute]).any?
    @tempalte.content_tag(:span, errors.to_sentence, class: "error")
    end
    end

    def method_missing(method, *args, &:block)
    if %r{ \A (?<labeled>labeled_)?
    (?<wrapped>\w+?)
    (?<with_errors>_with_errors)? \z}x =~ method and
    respond_to?(wrappted) and [labeled, with_errors].any?(&:present?)
    attribute, tags = args.first, []
    tags << label(attribute) if labeled.present?
    tags << send(wrapptted, *args, &block)
    tags << errors_for(attribute) if with_errors.present?
    tags.join(" ").html_safe
    else
    super
    end
    end
    end

    ```


    ``` ruby

    # ...

    module Blog
    class Application < Rails::Application

    # ...

    require "labled_fields_with_errors"
    config.action_view.default_form_builder = LabeledFieldsWithErrors
    config.action_view.field_error_proc = ->(field, _) { fieled }
    end
    end

    ```

    ``` erb
    <%= form_for @article do |f| %>
    <p> <%= f.text_field :subject %></p>
    <p> <%= f.labled_text_field :subject %></p>
    <p> <%= f.text_field_with_errors :subject %></p>
    <p> <%= f.labled_text_field_with_errors :subject %></p>
    <% end %>
    ```


    ``` html
    <!-- ... -->

    <p> <input id="article_subject" name="article[subject]" size="text" value="" /> </p>
    <p> <label for ="article_subject"> Subject </label>
    input id="article_subject" name="article[subject]" size="text" value="" /> </p>
    <p> <input id="article_subject" name="article[subject]" size="text" value="" />
    <span class="error"> can't be blank </span> </p>
    <p> <label for ="article_subject"> Subject </label>
    <input id="article_subject" name="article[subject]" size="text" value="" />
    <span class="error"> can't be blank </span> </p>
    <!-- ... -->

    ```

    ### 37. Inspire Theme Songs About Your Work

    * <http://www.confreaks.com/videos/529-farmhouseconf-ruby-hero-tenderlove>

    ### 38. Route Exceptions

    ``` ruby
    # ...

    module Blog
    class Application < Rails::Application
    # ...

    config.exceptions_app = routes
    end
    end
    ```

    ``` ruby
    Blog::Application.routes.dreaw do

    # ...
    match "/404", to: "erros#not_found"
    end
    ```

    ### 39. Route to Sinatra

    ``` ruby
    source 'https://rubygems.org'

    # ...
    gem "resque", require: "resque/server"

    ```

    ``` ruby
    module AdminValidator
    module_funtion

    def matches?(request)
    if (id = requires.env]["rack.session"]["user_id"])
    current_user = User.find_by_id(id)
    current_user.try(:admin?)
    else
    false
    end
    end
    end
    ```

    ``` ruby
    Blog::Application.routes.dreaw do

    # ...
    require "admin_validator"

    constraints Adminvalidator do
    mount Resque::Server, at: "/admin/resque"
    end
    end
    ```


    ### 40. Stream CSV to Users

    ``` ruby
    class ArticlesController < ApplicationController
    def index
    respond_to do |format|
    format.html do
    @articles = Article.all
    end
    end

    format.csv do
    headers["Content-Dispostion"] = %Q{attachment; filename="articles.csv"}
    self.response_body = Enumerator.new do |respons|
    csv = CSV.new(response, row_sep: "\n")
    csv << %w[Subject Created Status]
    Article.find_each do |article|
    csv << [article.subject,
    article.created_at.to_s(:long),
    article.status]
    end
    end
    end
    end
    end
    ```


    ### 41. Do Some Wortk in the Background

    ```
    $ rails g migration add_stats_to_articles stats:text
    ```

    ``` ruby
    class Article < ActiveRecord::Base
    # ...

    serialize :stats

    def calculate_stats
    words = Hash.new(0)
    body.to_s.scan(/S+/) { |word| words[word] +=1 }
    sleep 10 # simulate a lot of work
    slef.stats = { words: words }
    end
    end
    ```

    ``` ruby
    class Article < ActiveRecord::Base
    # ...

    require "thread"
    def self.queue; @queue ||= Queue.new end

    def self.thread
    @thread ||= Thread.new do
    while job = queue.pop
    job.call
    end
    end
    end

    thread # start the Thread
    end
    ```

    ``` ruby
    class Article < ActiveRecord::Base
    # ...

    after_create :add_stats

    def add_stats
    self.class.queue << -> { calculate_stats; save }
    end
    end
    ```

    ```
    % rails c
    Loading development environment in sandbox (Rails 3.2.3)
    >> Article.create!(subject: "Stats", body: "Lorem ipsum..."); Time.noew.strftime("%H:%M:%S")
    => "15:24:10"
    >> [Article.last.stats, Time.noew.strftime("%H:%M:%S")]
    => [nil, "15:24:13"]
    >> [Article.last.stats, Time.noew.strftime("%H:%M:%S")]
    => [{:words => {"Lorem"=>1, "ipsum"=>1, ....}}, "15:24:13"]
    >>
    ```

    ### 42. Publish a Static Site Using Rails

    ``` ruby

    Static::Application.configure do
    # ...

    # Show full error reports and disable caching
    config.consider_all_request_local = true
    config.action_controller.perform_caching = !![ENV["GENERATING_SITE"]

    # ...

    # Don't fallback to assets pipeline if a precompiled assets is missed

    config.assets.compie = ![ENV["GENERATING_SITE"]

    # Generate digest for assets URLs
    config.assets.digest = !![ENV["GENERATING_SITE"]
    end
    ```


    ``` ruby
    class ApplicationController < ActionController::Base
    protect_from_forgery

    if [ENV["GENERATING_SITE"]
    after_filter do |c|
    c.cache_page(nil, nil, Zlib::BEST_COMPRESSION)
    end
    end
    end
    ```


    ``` ruby
    require "open-uri"

    namespace :static do
    desc "Generate a static copy of the site"
    task :generate => %w[environment assets:precompile] do
    site = ENV.fetech("RSYNC_SITE_TO") { fail "Must set RSYNC_SITE_TO"}

    server = spawn( {"GENERATING_SITE" => "true"}, "bundle exec rails s thin -p 3001")

    sleep 10 # FIXME: start when server is up

    paths = %w[/]
    files = []
    while path - paths.shift
    files << File.join("public", path.sub(%r{/]z}, "/index") + ".html")
    File.unlink(files.last) if File.exist? files.last
    files << files.last + ".gz"
    File.unlink(files.last) if ile.exist? files.last
    page = open("http://localhost:3001#path") { |url| url.read }
    page.scan(/<a[^>]+href="([^"]+)"/) do link
    paths << link.first
    end


    system("rsync -a public #{site}")

    Process.kill("INT", server )
    Process.wait(server)
    system("bundle exec rake assets:clean")

    files.each do |file|
    File.unlink(file)
    end
    end
    end
    ```

    ```
    $ rake static:generate RSYNC_SITE_TO=/Users/james/Desktop
    ```
  2. xdite revised this gist Jul 14, 2012. 1 changed file with 12 additions and 10 deletions.
    22 changes: 12 additions & 10 deletions 42-things-1.md
    Original file line number Diff line number Diff line change
    @@ -30,20 +30,20 @@ end

    ### 3. Remind You of Things

    ```
    ``` ruby
    class UsersController < ApplicationController
    # TODO: Make it possible to create new users.
    end
    ```

    ```
    ``` ruby
    class User < ActiveRecord::Base
    # FIXME: Should token really be accessible?
    attr_accessible :bio, :email, :name, token
    end
    ```

    ```
    ``` ruby
    <% OPTIMIZE: Paginate this listing. %>
    <%= render Article.all %>
    ```
    @@ -70,6 +70,7 @@ app/controllers/users_controller.rb
    ```

    #### rake notes:fixme

    ```
    $rake notes:fixme
    app/controllers/users_controller.rb
    @@ -78,7 +79,7 @@ app/controllers/users_controller.rb

    #### rake notes:custom ANNOTATION=JEG2

    ```
    ``` ruby
    class Article M ActiveRecord::Base
    belongs_to :user
    attr_accessible :body, :subject
    @@ -137,7 +138,7 @@ Loading development environment ( Rails 3.2.3)

    ### 6. Use Non-WEBriock Servers in Development

    ```
    ``` ruby
    source 'https://rubygems.org'
    #
    group :developemnt do
    @@ -158,7 +159,7 @@ $ rails s thin

    * require Railtie, with config.custom in Railtie

    ```
    ``` ruby
    # lib/custom/railtie.rb
    module Custom
    class Railtie < Rails::Railtie
    @@ -169,9 +170,10 @@ end

    * You can configure plugins the same way you configure Rails

    ```
    ``` ruby
    # config/application.rb
    #

    require_relavtive "../lib/custom/railtie"
    module Blog
    class Application < Rails::Application
    @@ -197,7 +199,7 @@ $ rails g resources user name:string email:string token:string bio:text
    $ rails g resources user name email token:string{6} bio:text
    ```

    ```
    ``` ruby
    class CreateUsers < ActiveRecord::Migration
    def change
    create_table :users do |t|
    @@ -218,7 +220,7 @@ end
    $ rails g resource user name:index email:uniq token:string{6} bio:text
    ```

    ```
    ``` ruby
    class CreateUsers < ActiveRecord::Migration
    def change
    create_table :users do |t|
    @@ -233,4 +235,4 @@ class CreateUsers < ActiveRecord::Migration
    add_index :users, :email, :unique => true
    end
    end
    ```
    ```
  3. xdite revised this gist Jul 14, 2012. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion 42-things-1.md
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@ FridayHug.com <http://fridayhug.com>

    The Smallest Rails App <http://thesmallestrailsapp.com>

    ```
    ``` ruby
    %w(action_controller/railtie coderay).each &method(:require)

    run TheSmallestRailsApp ||= Class.new(Rails::Application) {
  4. xdite created this gist Jul 14, 2012.
    236 changes: 236 additions & 0 deletions 42-things-1.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,236 @@
    ### 1. Get You a Hug, Every Friday

    FridayHug.com <http://fridayhug.com>

    ### 2. Run From a Single File

    The Smallest Rails App <http://thesmallestrailsapp.com>

    ```
    %w(action_controller/railtie coderay).each &method(:require)
    run TheSmallestRailsApp ||= Class.new(Rails::Application) {
    config.secret_token = routes.append { root to: 'hello#world' }.inspect
    initialize!
    }
    class HelloController < ActionController::Base
    def world
    render inline: %Q{
    <!DOCTYPE html>
    <title>The Smallest Rails App</title>
    <h3>I am the smallest rails app!</h3>
    <p>Here is my source code:</p>
    #{CodeRay.scan_file(__FILE__, :ruby).div(line_numbers: :table)}
    <a href="https://github.com/artemave/thesmallestrailsapp.com">Make me smaller</a>
    }
    end
    end
    ```

    ### 3. Remind You of Things

    ```
    class UsersController < ApplicationController
    # TODO: Make it possible to create new users.
    end
    ```

    ```
    class User < ActiveRecord::Base
    # FIXME: Should token really be accessible?
    attr_accessible :bio, :email, :name, token
    end
    ```

    ```
    <% OPTIMIZE: Paginate this listing. %>
    <%= render Article.all %>
    ```

    #### rake notes

    ```
    $rake notes
    app/controllers/users_controller.rb
    * [ 2][TODO] Make it possible to create new users.
    app/modles/user.rb:
    * [ 2][FIXME] Should token really be accessible?
    app/views/articles/index.htmk.erb:
    * [ 2][OPTIMIZE] Paginate this listing.
    ```

    #### rake notes:todo
    ```
    $rake notes:todo
    app/controllers/users_controller.rb
    * [ 2] Make it possible to create new users.
    ```

    #### rake notes:fixme
    ```
    $rake notes:fixme
    app/controllers/users_controller.rb
    * [ 2] Should token really be accessible?
    ```

    #### rake notes:custom ANNOTATION=JEG2

    ```
    class Article M ActiveRecord::Base
    belongs_to :user
    attr_accessible :body, :subject
    # JEG2: Add that code from your blog here.
    end
    ```

    ```
    $ rake notes:custom ANNOTATION=JEG2
    app/modles/article.rb
    * [ 4] Add that code from your blog here.
    ```
    #### TextMate Bundles

    * Bundles > TODO > Show TODO List

    ### 4. Sandbox Your Console

    #### rails r

    ```
    $ rails r 'p [Article, Comment, User].map(&:count)'
    [0,0,0]
    ```

    #### rails c --sanbox

    rolls back changes

    ```
    $ rails c --sandbox
    Loading development environment in sandbox (Rails 3.2.3)
    Any modifications you make will be rolled back on exit
    >> jeg2 = User.create!(name: "Jame Edward Gray II")
    => #<User id: 1, name: "Jame Edward Gray II", …>
    >> article = Article.new(subject: "First Post").tap { |a| a.user = jeg2; a.save! }
    => #<Article id: 1, user_id: 1, ubject: "First Post", …>
    >> Comment.new(body: "I need to add this.").tap { |c| c.user, c.article = jeg2, article' c.save! }
    => #<Comment id: 1, user_id: 1, article_id: 1, body: "I need to add this.", …>
    >> [Article, Comment, User].map(&:count)
    => [1, 1, 1]
    >> exit
    $ rails r 'p [Article, Comment, User].map(&:count)'
    [0,0,0]
    ```
    ### 5. Run Helper Methods in the Console

    ```
    $ rails c
    Loading development environment ( Rails 3.2.3)
    >> helper.number_to_currency(100)
    >> "$100.00"
    >> helper.time_ago_in_words(3.days.ago)
    => "3 days"
    ```

    ### 6. Use Non-WEBriock Servers in Development

    ```
    source 'https://rubygems.org'
    # …
    group :developemnt do
    gem "thin"
    end
    ```

    ```
    $ rails s thin
    => Booting Thin
    => Rails 3.2.3 application starting in development on http://0.0.0.0:3000
    => Call with -d to detach
    >> Thin web server (v1.3.1 codename Triple Espresso)
    >> Maximum connections set to 1024
    >> Listening on 0.0.0.0:3000, CTRL+C to stop
    ```
    ### 7. Allow You to Tap into its Configuration

    * require Railtie, with config.custom in Railtie

    ```
    # lib/custom/railtie.rb
    module Custom
    class Railtie < Rails::Railtie
    config.custom = ActiveSupport::OrderedOptions.new
    end
    end
    ```

    * You can configure plugins the same way you configure Rails

    ```
    # config/application.rb
    # …
    require_relavtive "../lib/custom/railtie"
    module Blog
    class Application < Rails::Application
    # …
    config.custom.setting = 42
    end
    end
    ```

    ### 8. Keep You Entertained

    Ruby Dramas <http://rubydramas.com>

    ### 9. Understand Shorthand Migrations

    ```
    $ rails g resources user name:string email:string token:string bio:text
    ```

    * Default is string, can add limits

    ```
    $ rails g resources user name email token:string{6} bio:text
    ```

    ```
    class CreateUsers < ActiveRecord::Migration
    def change
    create_table :users do |t|
    t.string :name
    t.string :email
    t.string :token, :limit => 6
    t.text :bio
    t.timestamps
    end
    end
    end
    ```

    ### 10. Add Indexes to Migrations

    ```
    $ rails g resource user name:index email:uniq token:string{6} bio:text
    ```

    ```
    class CreateUsers < ActiveRecord::Migration
    def change
    create_table :users do |t|
    t.string :name
    t.string :email
    t.string :token, :limit => 6
    t.text :bio
    t.timestamps
    end
    add_index :users, :name
    add_index :users, :email, :unique => true
    end
    end
    ```