Archive for the ‘Solutions’ Category

Difference between render and display in merb

Use render for actions like create and new, where you don’t really want to share the xml or even want xml created. Or json for that matter.

Use display to render actions like index and show, where you do want to share the information via xml.

render means you want to render a template — or a string. display means you want to render a resource. so display will do what it can return something to the client

it checks for a template and if that’s missing calls #to_ on the model

# courtesy unagi-san

Here’s the render method on merb-core head and display method on merb-core head

How to uninstall all gems from your computer

sudo gem uninstall --a --ignore-dependencies .+

Thank you loopkid

Also here’s how to uninstall a particular long list of gems. I find this particularly useful for merb which has tons of gems.

1
sudo gem uninstall --a --ignore-dependencies merb.+

How to setup a remote git server and deploy from it with capistrano

1. Install Git on ALL computers (local, remote git, and remote web server)

A. For installation on a mac or windows computer, google the web.

B. For remote git server and remote web server (assumes you’re on ubuntu hardy or something similar)

mkdir ~/sources
cd ~/sources
wget http://kernel.org/pub/software/scm/git/git-1.6.0.tar.bz2
sudo apt-get build-dep git-core
tar xjf git-1.6.0.tar.bz2
cd git-1.6.0/
./configure
make
sudo make install

2. SSH into your git server and setup the remote repository

mkdir ~/git
cd ~/git
mkdir example.git
cd exmplae.git
git init

3. On your local computer create your local repository for your app

mkdir example
cd example
git init
touch README
git add README
git commit -m 'Initial import'
git remote add origin git@REMOTE_SERVER:git/example.git
git push origin master

4. Now you can deploy app with capistrano from your local machine

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#example deploy.rb
 
set :runner, "username"
set :use_sudo, false
 
# =============================================================================
# CUSTOM OPTIONS
# =============================================================================
set :user, "username"
set :application, "example"
set :domain, "domain.com"
 
role :app, domain, :cron => true
role :web, domain
role :db,  domain, :primary => true
 
# =============================================================================
# DATABASE OPTIONS
# =============================================================================
set :rails_env,       "production"
 
# =============================================================================
# DEPLOY TO
# =============================================================================
 
set :deploy_to, "/home/#{user}/apps/#{application}"
 
# =============================================================================
# REPOSITORY
# =============================================================================
set :repository,  "ssh://username@REMOTE_SERVER:3444/home/username/git/#{application}.git" # If using a NON-STANDARD PORT instead of default 22. For git server.
set :scm, "git"
set :branch, "master"
 
# =============================================================================
# SSH OPTIONS
# =============================================================================
default_run_options[:pty] = true
ssh_options[:paranoid] = false
ssh_options[:keys] = %w(/Users/username/.ssh/id_rsa)
ssh_options[:port] = 3333 # If using a NON-STANDARD PORT instead of default 22. For deployment server.
 
 
# =============================================================================
# RAKE TASKS & OTHER SERVER TASKS
# =============================================================================
 
namespace :cron do
  task :start, :roles => :app, :only => {:cron => true} do
    cron_tab = "#{shared_path}/cron.tab"
    run "mkdir -p #{shared_path}/log/cron"
 
    require 'erb'
    template = File.read("config/cron.erb")
    file = ERB.new(template).result(binding)
    put file, cron_tab, :mode => 0644
 
    # merge with the current crontab
    # fails with an empty crontab, which is acceptable
    run "crontab -l >> #{cron_tab}" rescue nil
 
    # install the new crontab
    run "crontab #{cron_tab}"
  end
end
 
namespace :cron do
  task :stop, :roles => :app, :only => {:cron => true} do
    cron_tmp = "#{shared_path}/cron.old"
    cron_tab = "#{shared_path}/cron.tab"
 
    begin
      # dump the current cron entries
      run "crontab -l > #{cron_tmp}"
 
      # remove any lines that contain the application name
      run "awk '{if ($0 !~ /#{application}/) print $0}' " +
        "#{cron_tmp} > #{cron_tab}"
 
      # replace the cron entries
      run "crontab #{cron_tab}"
    rescue
      # fails with an empty crontab, which is acceptable
    end
 
    # clean up
    run "rm -rf #{cron_tmp}"
  end
end
 
desc 'Fix images from disappearing'
task :fix_images, :roles => :app do
  %w{images}.each do |share|
    run "rm -rf #{release_path}/public/#{share}"
    run "mkdir -p #{shared_path}/system/#{share}"
    run "ln -nfs #{shared_path}/system/#{share} #{release_path}/public/#{share}"
  end
end
 
desc "Create symlink to public_html/#{domain}/public"
task :symlinkify do
  run "rm -rf /home/#{user}/public_html/#{domain}/public; ln -s #{current_path}/public /home/#{user}/public_html/#{domain}"
end
 
desc "Reload Apache"
task :reload_apache do
  sudo "/etc/init.d/apache2 reload"
end
 
# Edit this accordingly.
after "deploy", "deploy:migrations"
after "deploy:migrations", "deploy:cleanup"
after "deploy:cleanup", "fix_images"
after "fix_images", "symlinkify"
after "symlinkify", "reload_apache"

Resources:

How to Install Merb: Use thor to get merb:edge

First install dependencies you’ll probably need

sudo gem install erubis rake json_pure rspec rack hpricot mime-types ruby2ruby ParseTree memcache-client templater haml mailfactory sequel mongrel libxml-ruby english addressable builder

Install thor

We will use thor to track Merb from git HEAD - which just means that we will keep up with the latest development version.

mkdir ~/sources
cd ~/sources
git clone git://github.com/wycats/thor.git
cd thor
rake install

Install merb.thor file

I like to keep my code projects in their prospective framework/language folder. (i.e. in ~/documents/code/rails are my rails apps and in ~/documents/code/merb are my merb apps). I am going to put the merb.thor file in this merb folder.

cd ~/documents/code/merb/sources
curl -L http://merbivore.com/merb.thor > merb.thor

Use merb.thor file to install/update merb:edge

First, make sure you have the latest merb.thor file. Run this command again.

cd ~/documents/code/merb/sources
curl -L http://merbivore.com/merb.thor > merb.thor
# or alternatively you can run
thor merb:tasks:update

Install/update merb:edge

cd ~/documents/code/merb/sources
#sudo thor merb:edge --install #used this previously but now using the 3 following lines so that I get the merb-plugins gems like merb_helpers in there as well.
sudo thor merb:edge:core --install
sudo thor merb:edge:more --install
sudo thor merb:edge:plugins --install

You will get an output similar to this if installing for the first time.

Install datamapper as your orm

Aside:
What is an orm? It’s an object-realtional_mapping tool/language. ActiveRecord is the most well known if you are a rails developer. Datamapper seems to be the current most popular choice for merb developers (but don’t quote me on that. Merb is highly configurable and different orms - like ActiveRecord - might server your particular needs better). However, datamapper is a safe bet for now with it’s goal to be fast, thread-safe and feature rich. Plus, thor supports it. On a final note, if you don’t know which orm to use, use datamapper. It is awesome. Let wycats show you why.

cd ~/documents/code/merb/sources
sudo thor merb:edge:dm_core --install
sudo thor merb:edge:dm_more --install
#the following worked on my computer already installed with datamapper, but did not work on a fresh install on a server. Therefore, use the two lines above.
#thor dm:gems:wipe #to clean out any old datamapper gems
#thor dm:clone #to pull down the github datamapper repositories
#cd dm
#thor dm:install #to install the latest datamapper gems

However, the most recent Thor file did not install merb_datamapper (Sept 23 2008), therefore I also did:

cd ~/sources
git clone git://github.com/sam/dm-more.git
cd dm-more/merb_datamapper
rake install

Also, the most recent data_objects and do_mysql was not installed correctly (I was getting the uninitialized constant DataObjects::URI (NameError) like you see here)so I also did:

cd ~/sources
git clone git://github.com/sam/do.git
cd do
rake install

tzselect: changing the timezone on your slicehost server

use the command tzselect

I was having issues with my rails-based cronjobs inserting different dates because of a difference between the date on my server and the date on my rails app (using Los Angeles time). I needed to make them match to fix this problem so I changed the time on my server using tzselect.

Nevermind, that didn’t really work the way I thought it would. I ended up just changing the crontab runtime to reflect the difference in time between LA and London.

merb-auth beginner’s tutorial

THIS TUTORIAL IS CURRENTLY OUT OF DATE. Hassox has redone merb-auth and it is even better now. I’ll be updating this tutorial as soon as possible. 

===========

===========

===========

===========

 

(this assumes you’ve already setup merb using this tutorial or something similar)

Install the necessary gems

sudo gem install merb_has_flash
cd ~/sources
git clone git://github.com/hassox/merb-auth.git
cd merb-auth
sudo rake install

Setup init.rb and router.rb

#init.rb
 
dependencies "merb-more", "merb_helpers", "merb-assets", "dm-timestamps", "dm-validations", "merb-slices", "merb-auth", "merb_has_flash"
 
...
 
Merb::BootLoader.before_app_loads do
  Merb::Slices::config[:merb_auth][:layout] = :application
end
 
...
#router.rb
 
...
 
Merb::Router.prepare do |r|
  # Slices
  # ADD THIS FOR MERB-AUTH
  r.add_slice(:MerbAuth, :path => "", :default_routes => false) 
 
  # RESTful routes
  # r.resources :posts
  # This is the default route for /:controller/:action/:id
  # This is fine for most cases.  If you're heavily using resource-based
  # routes, you may want to comment/remove this line to prevent
  # clients from calling your create or destroy actions with a GET
  r.default_routes
 
  # Change this for your home page to be available at /
  # r.match('/').to(:controller => 'whatever', :action =>'index')
end

How to quickly copy a database from an old server to a new server

Resources:
Use the mysqldump command in conjunction with ssh

Upgrade your linksys WRT54G version 8 to DD-WRT and make it awesome

First follow these instructions for getting dd-wrt: Get Linux running on your Linksys Router (this is for version 8 of WRT54G. You can check the version by looking at the bottom of your router. i.e. ver 8)

Then boost your wireless range: Go to http://192.168.1.1 user: root password: pass. Click Wireless > Advanced Settings. Change TX Power to 70. Click Save and the click Apply Settings.

Next let’s extend the range of the network using an apple airport express.

Wireless > Wireless Security > WEP
Default transmit key: 1
Encryption: 128
Passphrase: whatever you want
Save the first key in a text document for later
Apply Settings

Then follow these instructions - How to setup WDS between a wireless router and an Airport Express. Making sure you have your linksys router connected to your dsl box, and then your apple airport express connected to your linksys router.

Merb and Chronic: Natural Language Date Parsing

This assumes you’ve already got started with merb, and that you are using datamapper as your orm.

NOTE: This DOESN’T validate the chronicfied date yet so strange words like gobblygoob will still get passed, and the form will get saved.

0.Install chronic gem

sudo gem install chronic

1. In init.rb make sure you include the chronic gem as well as the following gems.

1
dependencies "merb-more", "merb_helpers", "merb-assets", "dm-timestamps", "dm-validations", "chronic"

2. In your model.rb chronicfy the date with the datamapper before_valid? hook

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
  class Post
  include DataMapper::Resource
 
  property :id, Integer, :serial => true # A :serial property is an auto-incrementing key
  property :date, Date
  property :title, :String
  property :description, String
  property :created_at, DateTime
  property :updated_at, DateTime
 
  # see http://datamapper.org/docs/validations.html though there must be a way to refactor this cleaner
  validates_with_method :must_be_chronic
  def must_be_chronic
    if Chronic.parse(self.date).nil?
      [false, "is not a valid date. Try removing any commas."]
    else
      return true
    end
  end
 
  before :valid?, :chronicfy
  def chronicfy 
    self.date = Chronic.parse(self.date)
  end
 
end

3. In your view, change the date field to a text_field.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<h1>Posts controller, new action</h1>
 
<p>Edit this file in <tt>app/views/posts/new.html.erb</tt></p>
 
<%= form_for @post, :class => "post_form", :action => url(:posts) do %>
	<%= partial("posts/form") %>
<% end =%>
 
 
# here's the _form.rhtml partial
<%= error_messages_for @post %>
 
<p>
<%= text_field :date, :label => "Date<br />" %>
</p>
 
<p>
<%= text_field :title, :label => "Title<br />" %>
</p>
 
<p>
<%= text_field :description, :label => "Description<br />" %>
</p>

Merb Beginner’s Tutorial

WARNING: Merb development is moving fast, and this tutorial is already pretty much OUT OF DATE. I’ll try and have a new updated one soon. Merb 1.0 is coming out mid-October! The guys hacking on Merb are pretty darn amazing.

Installation
This is for the edge version - which I actually recommend right now since merb is still having growing pains.

(avoid using sudo gem install merb, etc, and what the slapp tutorial says. They are out of date and/or broken at the time of this writing)

Create an install location
I like to put my stuff in ~/documents/code

mkdir ~/documents/code
cd ~/documents/code

Install dependencies

gem install erubis rake json_pure rspec rack hpricot mime-types ruby2ruby ParseTree \
  memcache-client templater haml mailfactory sequel sake mongrel libxml-ruby english addressable builder

I had problems with sake when installing merb and datamapper on ubuntu 8.04.1 LTS hardy. Instead I used thor (see further below) and it worked nicely - as long as you installed the dependencies above.


Install Sake

sudo gem install ParseTree -v 2.1.1  # sake at the time of writing requires exactly 2.1.1 of ParseTree gem
sudo gem install ruby2ruby -v 1.1.8 # sake at the time of writing requires exactly 1.1.8 of ruby2ruby exactly
sudo gem install sake

Install Merb Edge
Merb is like your Rails, but much lighter and without all the rules. It’s made up of a series of gems which get installed with the following.

sake -i http://github.com/wycats/merb-more/tree/master%2Ftools%2Fmerb-dev.rake?raw=true
sake merb:clone
sake merb:install:all

Install DataMapper Edge
Datamapper is like ActiveRecord but apparently faster.

sake -i http://github.com/dkubb/dm-dev/tree/master/dm-dev.sake?raw=true
sake dm:clone
cd dm
sake dm:install

Install thor

cd ~/sources
git clone git://github.com/wycats/thor.git
cd thor
rake install

Install merb

cd ~/sources
thor install http://github.com/jackdempsey/merb-thor/tree/master%2Fmerb.thor?raw=true --as=merb
thor merb:clone
cd merb
thor merb:install

Install datamapper

cd ~/sources
thor install http://github.com/jackdempsey/dm-thor/tree/master%2Fdm.thor?raw=true --as=dm
thor dm:clone
cd dm
thor dm:install

Install Miscellaneous stuff you’ll probably need

sudo gem install do_mysql
sudo gem install rspec

Create your first app

cd ~/documents/code/merb
merb-gen app  # to get a list of all the options available
merb-gen app merbeer --testing-framework=rspec --template-engine=erb --orm=datamapper # i really don't see the advantage to haml yet so I choose erb as my template engine. haml in my opinion makes it harder to work with a designer who only knows css and html (as far as I can tell)
cd merbeer
mate .  # assuming you use textmate
rake dm:db:database_yaml

Put the following in the database.yml file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# This is a sample database file for the DataMapper ORM
:development: &defaults
  :adapter: mysql
  :database: merbeer_development
  :username: root
  :password: 
  :host: localhost
  :socket: /tmp/mysql.sock
  :encoding: utf8
 
:test:
  <<: *defaults
  :database: merbeer_test
 
:production:
  <<: *defaults
  :database: merbeer_production
merb-gen resource Beer name:string description:text created_at:datetime
rake dm:db:migrate

Edit apps/models/beer.rb & add property :id, Integer, :serial => true because DataMapper requires you to explicitly declare the primary key. It should look like the following.

1
2
3
4
5
6
7
8
9
class Beer
  include DataMapper::Resource
 
  property :id, Integer, :serial => true
  property :name, String
  property :description, Text
  property :created_at, DateTime
 
end

Create databse and rake migrations

rake dm:db:create
rake dm:db:automigrate

Add routes to router.rb (I have a feeling this will be done automatically once Merb 1.0 arrives this October 08)

1
2
3
4
5
6
7
Merb::Router.prepare do |r|
  # RESTful routes
  # r.resources :posts
  r.resources :beers
 
  r.default_routes
end

Now we can start to spec and build.

Wait, hold on one second. Create the test database and move the migrations over first.

rake MERB_ENV=test dm:db:create
rake MERB_ENV=test dm:db:automigrate
rake spec #output should be 1 example 0 failures and 1 pending. ok good.

Now let’s create our first spec. Edit specs/models/beer_spec.rb

1
2
3
4
5
6
7
8
9
10
require File.join( File.dirname(__FILE__), '..', "spec_helper" )
 
describe Beer do
 
  it "should should be valid when new" do
    beer = Beer.new
    beer.should be  #be_valid has become just plain be as far as I can tell
  end
 
end
rake spec # ok good. it should have passed

to be continued…