Saturday, September 27, 2008

Remove Gems By Prefix

If you are working with Merb or DM you know that approximately a gazillion gems are involved.  When, for whatever reason, I want to remove them it is a pain to do by hand.


Here is a simple script to help:

#!/bin/bash
prefix=$1
gem list --local | grep $prefix  | awk '{ print $1 }' | xargs sudo gem uninstall

I saved mine as remove_gem_by_prefix, gave it executable permissions and placed it in my path.

Now I can issue the commands:

$ remove_gem_by_prefix merb

or 

$ remove_gem_by_prefix dm

And they all get blasted.  You do need to be careful to make sure the prefix you provide is unique to the gems you wish to remove.

Saturday, September 13, 2008

Quick Remote Git Repository Creation Script

If you are using Git for your source code management, GitHub is an awesome tool. It especially shines for public projects where you freely allow others to fork your code and possibly pull patches back in.

Sometimes I'm just working on a project that I would prefer to keep in a private repository. GitHub provides paying accounts with such an option. However, I already have hosting accounts that are terribly underused. Here is a little script I use to create a remote git repository on one of my VPS accounts that I can then pull from and push to.

Prerequisites
A hosting account which you can ssh / scp into.

The Script

$ vim new_repo

#! /bin/sh
PWD=`pwd`

# You must adjust these variables for your specifc hosting account.
# Remote user you will connect as.
REMOTE_USER="admin"
# The IP address you will SSH / SCP to.
REMOTE_HOST="123.456.123.456"
# The remote path you wish to store your .git repositories in.
REMOTE_REPO_PATH="/home/admin/repos/"

if [ -d $1 ]; then
  echo "EXITING: Local directory '$1' already exists."
  exit 0
else
  mkdir $1
  cd $1
  git init-db
  touch README
  git add .
  git commit -m "Initial Repository Creation"
  cd ..
  git clone --bare $1/.git $1.git
  echo "** Copying new repository $1.git to $REMOTE_HOST:$REMOTE_REPO_PATH"
  scp -r $1.git $REMOTE_USER@$REMOTE_HOST:$REMOTE_REPO_PATH
  rm -rf $1.git
  rm -rf $1
  echo "** Cloning locally at $PWD/$1"
  git clone $REMOTE_USER@$REMOTE_HOST:$REMOTE_REPO_PATH$1.git
fi

exit 0

Or get it from GitHub

http://github.com/jpease/git-o-mator

Configuration

Of course, you will need to REMOTE_USER="admin" with an actual user on your hosting account, adjust REMOTE_HOST="123.456.123.456" to point to your accounts IP address, and edit REMOTE_REPO_PATH="/home/admin/repos/" with whatever path you wish to contain your Git repositories.

Once that is done, provide executable permissions.

$ chmod +x new_repo

That's it. Now if you execute:

$ ./new_repo testing

You will end up with /home/user/repos/testing.git on your remote host, and ./testing locally. From ./testing you can git push to send commits to the remote repository, and git pull to retrieve from the remote repository.

If you see room for improvement, I'm sure there is some, please leave a comment with your revision!

Monday, June 23, 2008

DataMapper: Many-to-many

You can define many-to-many associations using this syntax:

#item.rb
has n, :things, :through => Resource

#thing.rb
has n, :items, :through => Resource

In this case it will create a table items_things to manage the assignments. Easy enough. Depending on the relationship you are mapping out, it may make more sense to use the :through => :model syntax.

Now if you create an instance of an Item, you will get a method "things=". At first I thought this would be how you would assign a new Thing to your Item. Such as:

@item = Item.get(1)
@thing = Thing.get(1)
@item.things = @thing

FAIL! If you try adding a single Thing to your Item with this method you will receive a failure that the class you sent did not have a map method defined. Ah, ok. That makes sense, things= is obviously plural and will want an array of things. So how do you assign just one thing?

If you are unsure, a handy tool is to remember the "methods" method. So in this case you can try out:

@item.methods

You will see that you have not only a "things=" method, but also a plain old "things" method. If you try:

@item.things.methods

You will see that you have a << method, as should be expected. So to add our single Thing to our Item we do:

@item.things << @thing

That's it.

Friday, June 6, 2008

DataMapper: Parent / Child Relationship

I couldn't find an example at datamapper.org /docs for a parent child relationship.


After a little searching, I found the answer in the integration tests.  Here is the example:

class Node
include DataMapper::Resource

def self.default_repository_name
ADAPTER
end

property :id, Integer, :serial => true
property :name, String

has n, :children, :class_name => 'Node', :child_key => [ :parent_id ]
belongs_to :parent, :class_name => 'Node', :child_key => [ :parent_id ]

end

Hope that helps someone else.

Monday, March 3, 2008

Merb Monday: Vacation Edition

I'm on vacation visiting family (with limited Internet access). Back to semi-normal next week.

Monday, February 25, 2008

Merb Monday: The Leap Year Edition

News
Official documentation has been updated to include 0.9. Still a little light, but coming along. If you would like to help, create your own git branch and have at it!

Ivey had a baby. Congratulations!

Expect 0.9.1 (developer release) today (or soon).

You get an "extra" day this week. Use it wisely.

Teaser
Code name: Merblets.

Q&A

Q: What!? No RJS?

A: You can do anything rjs can do with *.js.erb templates (Answer by ezmobius)


Q: I read that Merb is template agnostic. What templates languages do I have available?

A: erb out of the box (erubis), haml (merb_haml as a dependency in init.rb), markaby (Answer by sqred)


Q: What does a named route in Merb look like?

A: r.match("/login").to(:controller => "Sessions", :action => "new").name(:login)
(Answer by jodo)


Q: Does Merb have a debugger tool?

A: You can use ruby-debug. Start Merb with the -D option to enable ruby-debug support.
Enter "debugger" somewhere in your code as a breakpoint. (Answer by jdempsey)


Q: How do I find out what version of Merb I'm using?

A: merb -v (Answer by ezmobius)


Q: How can I see the current routes?

A: merb -i
merb.show_routes
(Answer by ezmobius)


Q: Can the cookie session be used for large production apps?

A: As long as you don't store really sensitive info in the session then cookie sessions are fine (Answer by ezmobius)

Monday, February 18, 2008

Merb Monday: State of flux

This week's edition is a little short. Certainly not for lack of activity in #merb, but due to the continued disturbance in the force caused by the 0.9 transition.

0.5 to 0.9 is a big jump (no wonder they skipped 0.6, 0.7 and 0.8!) Most of the discussion this week continued to be related to the transition to 0.9 and trouble ticket type "stuff".

News
0.9 was released (kinda), however this is a "developer" release and still has some wrinkles to be ironed out before a general public release will be pushed to RubyForge. If you are anxious to give it a spin, check Merbivore.

It looks like there will likely be a 0.9.1 "developer" release in the near future. Once we get to a 0.9.x general public release things should settle down and this series should get back to normal.

merbful_authentication should soon be updated to be compatible with 0.9.

Required Reading
0.9 introduces some really cool changes. One of those is Rack integration. You should read Ezra's post "So merb-core is built on rack you say? Why should I care?"

Q: If I use ActiveRecord as the ORM, do I then use ActiveRecord's migrations (and its syntax) by default?

A: Yes. You can use ActiveRecord with Merb as you would with Rails. (Answer by amoeba)

Q: How do you generate an app in Merb 0.9?

A: ./script/generate is gone. In it's place now lives merb-gen.

merb-gen myapp # a normal merb app

merb-gen myapp --flat # a flattened app

merb-gen myapp --very-flat # a single-file app
(Answer by ivey)

Answer Of The Week

And the answer to many of the questions this week which followed the format of:

Q: _____________________ in Merb 0.9?

A: "It's not in -core anymore" (Answer by ivey)

Audience Participation

Q: Assuming you are using ActiveRecord with Merb, how can you share models with a Rails application?

If you leave your answer in the comments, I'll post it next week. (hint) (Question & link by seebg)

Monday, February 11, 2008

Merb Monday: "That's the spirit"

Tidbits from #merb for the week of Feb 4 - Feb 10.

A lot of the conversation this week revolved around the pre 0.9 release. Many of the questions involved bugs or other issues that one can expect in a pre-release. In general I didn't include them as they will quickly be outdated and likely be of little on going value.

Q: How do I install (freeze) gems within my application?

A: Navigate to the root of your Merb application.

gem install foo -i gems
In your merb.yml file include a line:
dependency "foo"
(Answer by wycats)

Q: How do I support a new MIME type? Say for an Atom feed.

A:
Merb.add_mime_type(:atom,:to_atom,%w[application/x-atom])
Replace application/x-atom with whatever the correct header for atom is then make a template: foo.atom.erb

In your controller, use:
provides :atom
(Answer by ezmobius)

Q: Where could I define a constant which would then be accessible in different views, but should have a different value depending on the environment merb is running in?

A: config/environment/*.rb where * represents the desired environment, for example development.rb.

Q: How do I find the current controller and action in the view?

A: In a helper you could create the two following methods.
def controller_name
controller.request.controller_name.split('_').first
end

def action_name
controller.request.action
end
(Answer by slurry)

Q: What happened to MERB_ENV?

A: Merb's application constants have been re-factored as follows:
Old constant : New method

MERB_FRAMEWORK_ROOT : Merb.framework_root
MERB_ROOT : Merb.root
MERB_VIEW_ROOT : Merb.view_path
MERB_SKELETON_DIR : Merb.skeleton_path
MERB_LOGGER : Merb.logger
MERB_PATHS : Merb.load_paths
MERB_ENV : Merb.environment
(Answer by slurry)

Q: Is there a way to list all the generators available?

A: ruby ./script/generate

Q: Where is the source now?

A: The Merb project has switched from using SVN to Git for source code management. With that change the source is now at Github. Specifically you will want to use wycats repo, which you can find at: git://github.com/wycats/

The source code is broken down into merb-core, merb-more, and merb-plugins.

For more information on how to work with Git, see "So you want to contribute to Merb-core".

Once you have cloned the Git repos to your local system, you will then move into that directory and issue a "rake install" command to build the gem.
(Answer by ivey)

Q: Where are bugs / tickets being tracked now?

A: Along with the move to Github, bugs and ticket tracking has been moved from DevJaVu over to Lighthouse, specifically at merb.lighthouseapp.com.

Answer of the week

Here is one little snippet of conversation that may provide the answer regardless of your specific problem:

Q: Can I do _____________?

A:
hassox: I guess so
hassox: but I can't really help you on it...
grrt: :) I'll see how far I get
hassox: that's the spirit :)
grrt: it's great to just explore

Sometimes it's best to just try something out.

Audience Participation

Q: Merb-core has methods "render" and "display". What's the difference?

Leave your answer in the comments. (Hint)

Monday, February 4, 2008

Merb Monday: Environment variables, partials, etc.

I see a lot questions asked and answered in the #merb IRC room.

Many of them are questions that later I wish I remembered the answer to! So I'm going to try to keep track of questions I see asked and answered and record them here for the benefit of myself and others, and hopefully publish them here every Monday.

I might re-phrase the questions and answers slightly, as the writing tends to be quite terse on IRC.

Q: How do you check the current environment in Merb? I'm looking for the Merb equivalent to RAILS_ENV.

A: Merb.environment (Answered by: Booster)

Q: How do you render partials?

A: You use the partial method.

Scenario 1: You wish to render a partial template found in the same directory as your action's view template.

partial :foo
This will look in the current directory for a file named _foo.html.erb

Scenario 2: You wish to render a partial template found in a different directory than the action's view template.
partial 'common/foo'
This will look for the file views/common/_foo.html.erb
(Answered by: jp_n9)

Q: I'm trying to run my db:migrate and I'm getting a "no such file to load -- spec/rake/spectask" error.

A: Make sure you have the rspec gem installed.
sudo gem install rspec
(Answered by: octopod)

Q: How do I start merb in production mode?

A: Use the -e option. For example,
merb -e production
For a complete list of parameters type:
merb --help
(Answered by: Phoop)

Q: How do I get Merb to log data to the log file?

A: Make sure that you start Merb as a daemon with the -d directive, this will cause output to be logged to the log file located in the log/ directory (instead of being output to the console window).
merb -d
(Answered by: ezmobius)

Q: How can I use HAML for my templates?

A: Name your files with the .html.haml extension instead of the default .html.erb extension.

Example: name.html.haml

Second, you need to edit dependencies.rb to include the line:
dependency "haml"
You will also need to have the haml gem installed on your system. Restarting Merb will also likely be required.
(Answered by: QaDeS, bradly)

Q: Is there an easy way to get the current URL in a merb view?

A: I think it's request.uri
(Answered by: hassox)

In my testing the request variable does not appear to be directly available from a view template. However if you need that information you can easily pass the entire request variable, or just request.uri, into your view from the controller.


Friday, January 18, 2008

Merb: Multiple CSS files, one server request.

In my previous post Continued Education: Performance Yahoo I referred to Steve Souder' book "High Performance Web Sites".

Rule #1 is "Make fewer HTTP requests."

Now we already know that Merb is "built for speed", but generally that is considered within the context of the server side of things.

I was happy to see that Merb also allows us to follow Souder's #1 Rule for making the client side snappy too. So how does Merb allow us to make fewer HTTP requests? By dynamically combining multiple stylesheet or script files into one.

Let's see some code!
It's this simple:


# app/views/layout/application.html.erb
<% require_css :reset %>
<% require_css :master %>
<%= include_required_css :bundle => true %>
We define the various CSS files we wish to be included using require_css (in this example reset.css and master.css), then by setting the :bundle => true paramenter everything will be served up in a single HTTP request in a file called all.css! Now that's pretty cool.

But wait there's more!
The same technique works for Javascripts too.
You can have the same functionality for your javascripts using this syntax:
<% require_js :foo $>
<%= include_required_js :bundle => true %>
But wait there's even more!
Now what is really cool is that you don't have to place your require_css or require_js statements only in the layout. You can place those in your views or even partials. That means that for any given request, the bundled file will only include the files that are needed for that specific view. Edit: It looks like you may need to manually define and uniquely name each possible combination of files. It also appears that a CSS file required in a view will appear first in the generated combined CSS file and thus be over ridden by the (likely) more general file defined in the layout - which probably isn't the desired behavior.

Getting it to work
By default the bundling action should only occur when in production mode. At the moment (Merb 0.5.2) it appears there is a bug and the bundling action doesn't realize when it is in production mode - so nothing happens.

What you need to do is edit your config/merb.yml file and uncomment the line that reads:
:bundle_assets: true
That's it! Should work. Enjoy.

One Gottcha
By forcing :bundle_assets to true in the merb.yml file, we are enabling this functionality for all environments instead of just for production. This isn't really ideal

Credits
Thanks to dudleyf in #merb for helping me figure this out. Thanks to codahale for writing the code for :bundle.