Archive for the ‘Code’ Category
Tuesday, September 20th, 2011
Many times, you need to access the node in hook_page_alter(). Traversing gets ugly, so I moved it out into this little helper.
1 2 3
| function _get_page_node ($page) {
return (isset($page['content']['system_main']['nodes'])) ? $page['content']['system_main']['nodes'][array_shift(array_keys($page['content']['system_main']['nodes']))]["#node"] : false;
} |
Drop this is template.php, and now you can do something like
1 2 3 4 5 6
| function YOURTHEME_page_alter(&$page) {
$node = _get_page_node($page);
if($node && $node->type == "article") {
// ... edit only article nodes ...
}
} |
Tags: drupal, drupal 7, theme
Posted in Code | 1 Comment »
Monday, January 10th, 2011
While trying to set up Capybara with Test::Unit, I ran into trouble finding documentation on how to do it. Ultimately, I found the answer in the gem’s README, but for those who just want to google-and-go, I figured I’d post this for you.
Simply, throw this in your Gemfile
1 2 3
| group :test do
gem 'capybara'
end |
and run `bundle`
Now, open up test/test_helper.rb: we’re going to require capybara, and then crack open the integration test class to include Capybara and pass it your app
1 2 3 4 5 6 7 8
| # test_helper.rb
...
include Capybara
class ActionDispatch::IntegrationTest
include Capybara
Capybara.app = Issuepad::Application
end |
That should do it, let me know if you run into any other issues.
Posted in Code | 4 Comments »
Thursday, November 18th, 2010
Just taking some time to let you in on another gotcha. Hopefully, this saves people some aggravation some day.
While working on Kludge, we took a RESTful approach and built our controller like so:
1 2 3 4 5
| class ProjectsController < ApplicationController
def update
@project = Project.find(params[:id]).update_attributes(params[:project])
end
end |
While this works, it doesn’t offer you any protection that evil users may try to update projects that don’t belong to them. A better approach is to scope the projects to that belong to the account. So we updated the action to the following:
1 2 3 4 5
| class ProjectsController < ApplicationController
def update
@project = current_account.projects.find(params[:id]).update_attributes(params[:project])
end
end |
…and we got an error!
1 2
| ActiveRecord::ReadOnlyRecord (ActiveRecord::ReadOnlyRecord):
app/controllers/projects_controller.rb:45:in `update' |
This error arises because Rails makes all associations read-only. Since projects is now an association to account, we need to force readonly to false in the account model:
1 2 3 4
| class Account < ActiveRecord::Base
has_many :clients
has_many :projects, :through => :clients, :readonly => :false
end |
However, this will still throw the same error message! After googling, IRC-ing, and crying … I finally got the answer through brute-force trial and error. Turns out, :readonly does not accept the symbol :false, and only the literal false. Changing the following will make your test green:
1 2 3 4
| class Account < ActiveRecord::Base
has_many :clients
has_many :projects, :through => :clients, :readonly => false # <-- no longer a symbol
end |
Tags: gotcha, rails
Posted in Code | 2 Comments »
Monday, July 19th, 2010
This may bite you in the ass if you are upgrading a Rails app from 2 to 3: ‘Mail’ is now a reserved model name. That means, if you currently have a model app/models/mail.rb, and/or a class defined as class Mail < AR::Base (for instance), it will collide with the new Mail class in Rails 3, and possibly throw this error
1
| undefined method `transfer_encoding' for class `Mail::Message' |
That is because Rails defines Mail.transfer_encoding in it’s Mail class, and your’s is over-riding it. The quick fix: rename your class and your file name.
Tags: rails
Posted in Code | No Comments »
Thursday, June 10th, 2010
While attending this year’s RailsConf in Baltimore, there was much excitement in the air about Rails 3. This was perpetuated by the fact that the Rails core team pushed Rails 3, Beta 3 & 4 during the conference. While there are so many awesome new things that Rails 3 is providing, and I strongly encourage everyone to move over to it as soon as they can, I want to talk today about Rack, and how it is allowing your to optimize your Rails app like never before.
Nice Rack.
If you are new to a lot of the things going on in Rails 3, you probably aren’t to familiar with the concept of Rack. The story goes like this: before Rails 3, all of the things that the Rails framework provides you, like session handling, parsing the parameters, and other conveniences that Rails provides you pertaining to requests, were tightly coupled to the Rails code base. In the early days of Rails, this was no big deal; we had these tools and we loved them. However, as Rails grew, and the apps built on Rails had more demanding requirements, we found situations where these conveniences add a lot of not needed overhead. For example, let’s say we wanted to have a Rails application whose sole responsibility was to accept uploaded files that we save to a server. You wouldn’t necessarily need session handling, cookies, flash, etc. Also, you may have written a great library that is better optimized or offers more hooks to certain ingrained Rails functionality for your application that you would like to use instead. Enter Rails 3.
In Rails 3, the framework gutted many of these great features out of the framework and into this concept of a Rack. We’ll talk about what Rack is in just a second, but it is important to note that the key advantage hear is that these awesome conveniences can be taken out of your application stack (or enhanced) to optimize them to suite your application’s need.
Anatomy of a Rack
Ok, ok … so what is a Rack? Rack is simply an interface that sits in between your web server and your application.

When a request comes into a Rails app, before it encounters your application code, it will run through your Rack. The rack is a daisy-chained library of classes, each of which have different responsibilities, all of which are the dominant set-ups that need to be done for every request (sessions, params, etc).
Components
A Rack application is simply a class which defines a method, #call. This method receives a parameter, the current set up environment hash, commonly named “env”. The required return value of that method is an array composed of exactly three elements:
- The status code (200, 404, etc.)
- The headers for the request
- The response body
Note: The response body must respond to #each, therefore you will commonly find it in an array ( [my_response]) or a class mixed in with Enumerable.
The next Rack application inline to fire in your middleware will make a call to #call when it initializes and will receive its return value (the response / header / body array) as a parameter to #initialize, commonly labeled “app”.
Enough talking, let’s looks at code.
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
| module Rack
# The Rack::Static middleware intercepts requests for static files
# (javascript files, images, stylesheets, etc) based on the url prefixes
# passed in the options, and serves them using a Rack::File object. This
# allows a Rack stack to serve both static and dynamic content.
#
# Examples:
# use Rack::Static, :urls => ["/media"]
# will serve all requests beginning with /media from the "media" folder
# located in the current directory (ie media/*).
#
# use Rack::Static, :urls => ["/css", "/images"], :root => "public"
# will serve all requests beginning with /css or /images from the folder
# "public" in the current directory (ie public/css/* and public/images/*)
class Static
def initialize(app, options={})
@app = app
@urls = options[:urls] || ["/favicon.ico"]
root = options[:root] || Dir.pwd
@file_server = Rack::File.new(root)
end
def call(env)
path = env["PATH_INFO"]
can_serve = @urls.any? { |url| path.index(url) == 0 }
if can_serve
@file_server.call(env)
else
@app.call(env)
end
end
end
end |
So here is the first Rack application in a default Rails 3 stack, which is responsible for serving back static files. As you can see, it’s #initialize receives “app” as a first parameter, which would be the response of #call from the previous Rack app. For this Rack, the #call function doesn’t create it’s own array to return, it simply loads a static file if it finds it with Rack::File, or just passes the current environment silently if there is no static file.
Closing
The best way to learn what rack can do for you is to look into the code for the current Rails 3 stack and see what it does. You can get a list of your rack stack by running:
See also the Official Rack Project site for super easy documentation and explanations.
Tags: rack, rails
Posted in Code | No Comments »
Wednesday, February 17th, 2010
Many times, you may find yourself interested in moving some of your logic outside of the view and into a model, so that you can re-use it throughout your app. But sometimes, the method you may want to define needs to be on an association of two models, and not on the models themselves.
As a real world scenario, imagine you are making an online game in which two models exist, Game and Score. The Game model keeps track of when the game was started, who started it, the level of difficulty, etc. The Score model keeps track of the value of the score, the round the score was done in, and the time the score was placed. The Game model has many Score models. Obviously, when the game is over, we are going to want to be able to see the total score. But what model do we define the method on? The Game model, itself, doesn’t have any scores and a Score object only knows about itself and not all the others that belong to the parent Game object.
This is a situation where the method needs to be defined on the association of Game and Score. Anytime the value you are trying to obtain can only be calculated with a parent and a child of an association, then you need to define the method on the association.
How to define it
Turns out that defining the method is a little trivial. The has_many method, used for creating one-to-many relationships, accepts a block in which you can define methods. Inside that block, self is set to the collection of children in the relationship. So now to define your total_score method:
1 2 3 4 5 6 7 8 9
| class Game < ActiveRecord::Base
has_many :scores do
def total_score
total = 0
self.each { |score| total += score.value }
total
end
end
end |
Then, in the app …
1 2 3 4 5 6 7
| g = Game.create(:user_id => 1)
g.scores.build(:value=>20)
g.scores.build(:value=>40)
g.scores.build(:value=>60)
g.save
g.scores.total_score
# 120 |
Tags: model, rails, ruby
Posted in Code | No Comments »
Monday, January 25th, 2010
So you start working inside of a trunk checkout of a Subversion repo, thinking that you will just be making a quick update. Once you start working, you realize it might have been better to make a branch to work on the feature separately from the trunk? Fear not! As Floyd Price from CodeSpaces points out, the process is pretty simple when you think about what you want to get done.
Technically, if you have not committed the changes into the trunk yet, you are dealing with the most up to date version of the trunk. If you were create a new branch from the trunk, they’d both be on the same page, sans your new edits.
Your current trunk checkout: A + B
A new branch: A
To make the new branch, run:
#svn cp trunk_repo_path branch_repo_path/new-name
svn cp http://example.com/repo/trunk http://example.com/repo/branches/new-branch
Now, in your current trunk repo check out you’ve been working in, switch the URL to be the new branch
svn switch http://example.com/repo/branches/new-branch .
If you run `svn st`, you will see the same modified files, but if you run `svn info` you will see the checkout’s URL now points to the branch, and you are free to commint
svn commit -m "first of commit new feature"
Hope this helps.
Tags: svn
Posted in Code | No Comments »
Thursday, December 31st, 2009
There was a little bit of jumping around to figure this all of, so I figured I’d put it all in one place here
Installing Ruby 1.9
- Download and Unpackage Ruby from http://www.ruby-lang.org/en/downloads/, the cd into the dir
- Run `autoconf`
- Run `./configure –enable-shared –with-readline-dir=/usr/local`
- Run `make && sudo make install`
- Add /usr/local/bin to $PATH (most likely in ~/.profile or ~/.bash_profile)
- Run `ruby -v` and ensure it now says version 1.9.1
Installing Gems
sudo gem install -v=2.3.5 rails sqlite3-ruby rspec-rails cucumber-rails webrat -v=1.2.3 test-unit database_cleaner
Loading RSpec and Cucumber
In your app..
script/generate rspec
script/generate cucumber
Then open features/support/env.rb and comment out line #18 to remove warning when you run cucumber
You should be all set, if not, leave me a comment – I’ll be pretty quick about responding to them.
Tags: rails
Posted in Code | No Comments »
Wednesday, December 23rd, 2009
You probably already know that you can add child models relationships through the parent model once you have set up your models appropriately:
BlogPost < ActiveRecord::Base
has_many :comments
end
Comment < ActiveRecord::Base
belongs_to :blogpost
end
..and then you can do something like:
@blog = BlogPost.new(:title => "My First Post")
@comment = Comment.new(:body => "Great Post!")
@blog << @comment
@blog.save
We use the << method to make a foreign key relationship. When we save the blogpost model, it automagically saves the @comment model, and associates it with blogpost record via a foreign key, so that we can later say
puts @blog.comment.first.body
# "Great Post!"
But, what you may have not known about is Nested Attributes. This is a slick little feature, turned off by default, that allows you to create the child model via parameters of the parent model. To enable it, simply add this method call to the parent model:
BlogPost < ActiveRecord::Base
has_many :comments
accepts_nested_attributes_for :comments
end
Now, you can create the same blog/comment models & relationship with a quicker syntax:
@blog = BlogPost.new(:name => "My First Post", :comments_attributes => [{ :body => "Great Post!" }])
@blog.save
Upon saving, this will create the BlogPost, create the Comment, and set up the foreign key relationship. Sick!
To learn more, check out: http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
Tags: rails
Posted in Code | No Comments »
Thursday, December 17th, 2009
Here is a quick code snippet to put that pretty, pipe-seperated navigation into the bottom of your site, so that Google can eat it all up.
foreach(menu_navigation_links("primary-links", 1) as $m):
$arrNav[] = l($m['title'], $m['href']);
endforeach;
echo implode(" | ", $arrNav);
Substitue “primary-links” for the internal menu name of your choice. Enjoy!
Tags: drup
Posted in Code | 1 Comment »