Ruby hashes & symbols

Leave a comment

Some notes from Michael Hartl’s excellent Rails tutorial on the differences between Hashes, Symbols, and others stuff.

https://www.railstutorial.org/book/_single-page#sec-other_data_structures

Hashes

Hashes are arrays that aren’t limit to integer indexes. Their indexes, or keys, can be almost any object. For example can use strings as keys.

user = {}                          # {} is an empty hash.
user["first_name"] = "Michael"     # Key "first_name", value "Michael"

Instead of defining hashes one item at a time using square brackets, it’s easy to use a literal representation with keys and values separated by =>, called a “hashrocket”:

user = { "first_name" => "foo", "last_name" => "bar" } # hash from hash rocket

Symbols

While strings are fine as hash keys, in Rails symbols are much more popular. Symbols look like strings but are prefixed with a colon. For example :name is a symbol. Think of symbols as strings without all the baggage (faster all at once comparison).

user = { :name => "foo", :email => "bar" } # hash from symbol & hash rocket

Since symbols are so popular, Ruby no supports a new syntax for this special case:

user = { name: "foo", email: "bar" } # hash made from symbols

Note it can get confusing:

{ :name => "foo" }
{ name: "bar" }

:name is a valid symbol but name: has no meaning by itself (only has meaning inside a hash).

rvm management workflow

Leave a comment

Here are some notes to remind me how to setup and flip between various ruby configurations.

Ruby setup

rvm list (current versions of ruby installed locally)
rvm list known (all known versions)
rvm 2.1.3 (to switch to this version of ruby)
rvm install 2.1.3
rvm --default use 2.1.3
rvm use system --default (set back to Mac default)

Rails setup
Rails is setup on a per ruby install basis. So just because you install rails once, doesn’t mean it is available for all rubies.

To see what gems you currently have installed type

gem list

To create a named gemset for this combination of ruby & rails go:

rvm gemset create rails416
rvm gemset list

Now link this version of ruby new version of rails:

rvm 2.1.3@rails416

gemsets for ruby-2.1.3 (found in /Users/jrasmusson/.rvm/gems/ruby-2.1.3)
(default)
global
rails416

Now install Rails.

gem install rails -v 4.1.8 --no-ri --no-rdoc

Now to flip between environments we go:

$ rvm 2.1.3@rails410 ; rails --version
Rails 4.1.0
$ rvm 2.1.3@rails320 ; rails --version
Rails 3.2.0

If libxml2 is missing nokogiri

$ gem install nokogiri -- --use-system-libraries
$ bundle config build.nokogiri --use-system-libraries
$ bundle install

If fails on libv8

$ gem uninstall libv8
$ brew install v8
$ gem install therubyracer -v '0.12.1'
$ bundle install
$ gem install libv8 -v '3.16.14.7' -- --with-system-v8
$ bundle install

http://stackoverflow.com/questions/19673714/error-installing-libv8-error-failed-to-build-gem-native-extension

If pg problems

.
$ bundle install --without production
.

Links that help
http://rvm.io/workflow/examples
http://rvm.io/rubies/default
http://rvm.io/gemsets/basics

How to setup RSpec from scratch

Leave a comment

> mkdir foo
> cd foo
> gem install bundler

Gemfile

source 'https://rubygems.org'
gem 'minitest', '~> 5.3.4'
gem 'rspec', '2.14.1'
gem 'capybara', '2.3.0'
gem 'selenium-webdriver'
> bundle install
> rspec --init

lib/zombie.rb

class Zombie
  attr_accessor :name
 
  def initialize
    @name = 'Ash'
  end
 
end

spec/lib/zombie_spec.rb

require 'zombie'

describe Zombie do

  it 'is named Ash' do
    zombie = Zombie.new
    expect(zombie.name).to eq('Ash')
  end

end

> rspec spec/lib/zombie_spec.rb

Trouble shooting

Use this is having trouble with named routes and rspec.

# Added below
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'

RSpec.configure do |config|
  config.treat_symbols_as_metadata_keys_with_true_values = true
  config.run_all_when_everything_filtered = true
  config.filter_run :focus
  config.order = 'random'
  config.use_transactional_fixtures = true


  config.include Capybara::DSL # JR - added to get paths working
end

How to setup an new Ruby project with tests

Leave a comment

ruby-tests-directory-structure

Create a new directory
> mkdir foo
> cd foo

Install bundler
> gem install bundler

Create a gem file and add the following gem
> vi Gemfile

source 'https://rubygems.org'
gem 'minitest', '~> 5.3.4'

> bundle install

Create the following directory structure
> mkdir lib test

Create a class
> vi lib/meme.rb

class Meme
  def i_can_has_cheezburger?
    "OHAI!"
  end

  def will_it_blend?
    "YES!"
  end
end

Create a minitest
> vi test/test_meme.rb

require "minitest/autorun"
require_relative '../lib/meme'

class TestMeme < Minitest::Test
  def setup
    @meme = Meme.new
  end

  def test_that_kitty_can_eat
    assert_equal "OHAI!", @meme.i_can_has_cheezburger?
  end

  def test_that_it_will_not_blend
    refute_match /^no/i, @meme.will_it_blend?
  end

  def test_that_will_be_skipped
    skip "test this later"
  end
end

or BDD style

require 'minitest/autorun'
require_relative '../lib/meme'

describe Meme do
  before do
    @meme = Meme.new
  end

  describe 'when asked about cheeseburgers' do
    it 'must respond positively' do
      @meme.i_can_has_cheezburger?.must_equal 'OHAI!'
    end
  end

end

Run the test
> ruby test/test_meme.rb

3 runs, 3 assertions, 0 failures, 0 errors, 1 skips

Voila!

Links that help
http://ruby.learncodethehardway.org/book/ex46.html
http://www.airpair.com/testing/learn-ruby-test-driven-development
https://github.com/seattlerb/minitest
http://bundler.io/

How to bundle open a gem from command line using RubyMine

1 Comment

Edit your ~/.bash_profile and add:
export EDITOR=/Applications/RubyMine.app/Contents/MacOS/rubymine

Then navigate to your project and type

> bundle open ‘gem’

How to pass variable to partials in Rails

Leave a comment

Define your partial

_next_prev_nav.erb

<ul class="pager">
  <li class="previous">
    <%= link_to "&larr; Previous".html_safe, prev_url  %>
  </li>
  <li class="next">
    <%= link_to "Next &rarr;".html_safe, next_url  %>
  </li>
</ul>

You can see here prev_url and next_url are variables that I want to pass values to when I call this partial.

Then call it like this:

          <%= render 'shared/next_prev_nav', :prev_url => "http://foo.com", :next_url => "http://bar.com" %>

Rails has_many example

Leave a comment

Here are some notes on how to create a has_many relationship and the corresponding APIs for each entity.

> rails new hasMany
> rails g scaffold User name:string
> rails g scaffold Micropost content:string user_id:integer

user.rb

class User < ActiveRecord::Base
   has_many :microposts, dependent: :destroy
   end

micropost.rb

class Micropost < ActiveRecord::Base
  belongs_to :user
end

Sample calls

> micropost.user
> user.microposts
> user.microposts.create(arg)
> user.microposts.build
> @micropost = user.microposts.build(content: “Lorem ipsum”)

Links that help
http://ruby.railstutorial.org/book/ruby-on-rails-tutorial#sec-demo_user_has_many_microposts

How to read files from dir and generate html output

2 Comments

When creating videos, I take snapshots of keynote, upload to website, and then manually handcraft the html to include in the show notes. It’s slow, tedious, and not a lot of fun.

So today I created a ruby script to do this for me.

imageconverter.rb

date = ARGV[0] # 2013/06
alt = ARGV[1] # iteration mechanics
basedir = "/Users/jrasmusson/Desktop"
files = Dir.glob(basedir + "/*.png")
files.each do |k|   puts "<img src=\"http://xxx/" + date + "/" + File.basename(k) + "?w=500\" alt=\"" + alt + "\" /><hr>"
end

> ruby imageconverter.rb 2013/06 “iteration mechanics” | pbcopy

<img src="http://xxx/2013/06/im-analysis.png?w=500" alt="iteration mechanics" /><hr>
<img src="http://xxx/2013/06/im-check-the-work.png?w=500" alt="iteration mechanics" /><hr>
<img src="http://xxx/2013/06/im-do-the-work.png?w=500" alt="iteration mechanics" /><hr>
...

To see the output on screen, run without the pbcopy mac command at the end which copies to clip board.

The only thing I haven’t been able to do is make this ruby script globally available from any directory (like a bash script).

If anyone has any ideas on how to do that I would be very grateful.

Tips for sending email via Rails

2 Comments

Some reminders for how to configure email via a rails application.

Watch this:
http://railscasts.com/episodes/274-remember-me-reset-password

Add this:

production.rb

  config.action_mailer.delivery_method = :smtp
  config.action_mailer.raise_delivery_errors = true
  config.action_mailer.smtp_settings = {
    :address              => "smtp.gmail.com",
    :port                 => 587,
    :domain               => 'foo.com',
    :user_name            => 'foo@bar.com',
    :password             => 'xxx',
    :authentication       => 'plain',
    :enable_starttls_auto => true
  }

  config.action_mailer.default_url_options = { :host => "foo.com" }

And ignore the Heroku blog post about emailing via gmail.

Links that help

http://guides.rubyonrails.org/action_mailer_basics.html#action-mailer-configuration-for-gmail

Tips
– restart prod server

How to add a boolean column to a table in rails

Leave a comment

As a reminder to myself, here are some notes on how to add a boolean column to a table in rails3.

Step 1: Create migration

rails generate migration add_public_to_listings admin:boolean

Step 2: Write unit tests on model

listing_spec.rb

    describe "admin attribute" do

      before(:each) do
        @listing = @user.listings.create!(@attr)
      end

      it "should respond to public" do
        assert_respond_to(@listing, :public)
      end

      it "should not be public be default" do
        assert !@listing.public
      end

      it "should be converible" do
        @listing.toggle!(:public)
        assert @listing.public
      end
    end

Step 3: Update test data

populate.rake

def make_listings
  puts "----------------"
  puts "--- listings ---"
  puts "----------------"

  myUser = User.find_by_email("a@a.com")

  ls1 = myUser.listings.create!(:title => "The Mona Lisa",
                               :description => "Master peice",
                               :category_id => 2,
                               :address => "T3H0E2",
                               :location => "Calgary, Alberta, Canada")
  ls1.toggle!(:public) 

Note: We set the :public value through the toogle for security reasons. Only those variables exposed via attr_accessible

class Listing < ActiveRecord::Base
attr_accessible :title, :description, :category_id, :address, :location

can be set through mass assignment. This prevents bad guys from changing values like this:

put /listings/17?public=1

Thanks again Michael for the great example.

Older Entries

%d bloggers like this: