Archive for the ‘Code’ Category

Get the page node in hook_page_alter in Drupal 7

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: , ,
Posted in Code | 1 Comment »

Configure Test::Unit and Capybara

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 »

ReadOnly needs to be set to true or false, not :true or :false

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: ,
Posted in Code | 2 Comments »

‘Mail’ is a resevered model name in Rails 3

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:
Posted in Code | No Comments »

Working With Rack in Rails 3

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:

1
rake middleware

See also the Official Rack Project site for super easy documentation and explanations.

Tags: ,
Posted in Code | No Comments »

Adding Methods on Associations in Rails

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: , ,
Posted in Code | 2 Comments »

Turn Current Working Trunk Into a Branch in SVN

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:
Posted in Code | No Comments »

Installing Ruby 1.9, Rails 2.3.5 and Getting RSpec/Cucumber working on Mac

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:
Posted in Code | No Comments »

Update Child Model From Parent’s Attributes in Rails

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:
Posted in Code | No Comments »

Display navigation in footer in Drupal

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:
Posted in Code | 1 Comment »