Friday, November 30, 2007

RSpec and Attachment_Fu

I'm barely even a beginner at using RSpec, but one of the first tests I needed to do involved Attachment_Fu.

Here's what I did to get my model to pass validation:

require File.dirname(__FILE__) + '/../spec_helper'

describe Image do
#
# I created the spec/images directory and placed this
# test image prior to running this test
#
TEST_FILE = RAILS_ROOT + '/spec/images/728x90_test_image.jpg'
before(:each) do
@image = Image.new
@image.name = "My Image"
@image.destination_url = "http://andy.devwisdom.com"
@image.uploaded_data =
ActionController::TestUploadedFile.new(TEST_FILE,'image/jpg')
#
# This is the key...Have Attachment_Fu do it's thing and
# process the uploaded data
#
@image.send :process_attachment
end


it "should be valid" do
@image.should be_valid
end
end

Thursday, November 29, 2007

nearest power of 2

This is one of the reasons I'm a fan of Ruby:

class << Math
def log2(n)
log(n) / log(2)
end
end

class Integer
def nearest_power_of_2
2**(Math.log2(self).floor)
end
end


47.nearest_power_of_2 => 32

Wednesday, November 28, 2007

initializers

Rails 2.o has a new organizational concept with the addition of the config/initializers directory. By default you will have the inflections.rb and mime_types.rb initializers.

I have used a few different approaches to organizing application constants. However, no approach felt right. I didn't like 'polluting' the environment.rb with them because I never thought that was the appropriate place. Creating a file in the lib dir or a plugin worked well, but just seemed odd and I had very little reasoning to defend that decision other than I didn't like using the environment.rb (more on the environment.rb usage later).

Having the Rails team make a standard location is very nice.

Big thanks to the Rails team. You guys/gals are doing a fantastic job.

find_or_initialize/create_by_<field>

A new 'discovery' today. I love finding the occasional meta programming derived method that isn't explicitly listed with the other methods on the rails api site.

find_or_initialize_by_<field>
find_or_create_by_
<field>

They do what you think. For example if I did:

user = User.find_or_initialize_by_login("stonean")

If the record exists, all is good. If not, well then you can either get an newly initialized object (not saved) or a newly created object (saved). I think the find_or_initialize_by method will get more use, but I do see uses for the find_or_create_by method. So, goodness all 'round.

Tuesday, November 20, 2007

Komodo Edit - Indenting

To indent a bunch of lines at once just highlight them and hit the Tab key (Shift-Tab to undo indention).

Starting lighttpd

I didn't want lighttpd starting on boot so I removed it:
sudo launchctl unload -w /Library/LaunchDaemons/org.macports.lighttpd.plist

But then I couldn't figure out how to start it. Bummer. Then I finally found:
/opt/local/etc/LaunchDaemons/org.macports.lighttpd/lighttpd.wrapper start

Monday, November 19, 2007

gem server

In the category of why I haven't I used this yet (duh!):

run: gem_server
to run as daemon: gem_server --daemon

then access: localhost:8808

Documentation for your installed gems. Nice.

If you don't have any documentation, run: gem rdoc --all

This will generate the docs for all the gems installed on your system.

Note: gem_server has been deprecated in favor of gem server. However, the daemon flag doesn't work for me. That's a bummer.

Update 12/21/2007:
The release of gems 1.0.0 fixes the daemon issue, so you can now run:
gem server --daemon

RubyOnRails Interview Questions - 201

These questions are intended to query for intermediate level knowledge of the Rails framework.

Q) I have two tables, users and addresses. The users table has a foreign key column to the addresses table called address_id. This is a one user to a one address setup. How do I represent that relationship in the User ActiveRecord model?

A) Add the line: belongs_to(:address) to the User class.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) I have two tables, users and comments. The comments table has a foreign key to the users table. This is a one user to many comments setup. How do I represent that relationship in the Users model?

A) Add the line: has_many(:comments) to the User class.

Note: could have has_many(:comment) - singular - , but that doesn't make semantic sense for a has_many relationship.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) I have two tables, users and groups. Users can belong to multiple groups and groups can have multiple users. I've created a groups_users join table to hold the relationship. How do I represent that relationship in the Users model?

A) Add the line: has_and_belongs_to_many(:groups) to the Users table.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) Why was the table called groups_users and not users_groups?

A) Rails convention is to alphabetize the names of the tables that make up the join table. This allows Rails to find the correct table.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) If I wanted to write a method that was available to all of my views where would I put that method?

A) The method could be put in the RAILS_ROOT/app/helpers/application_helper.rb

Note: You could put the method in another file and then include the module into the application_helper.

Note 2: If you want a helper method only available to one view, put in the helper of the corresponding controller. If you have a users_controller, Rails expects a users_helper in the RAILS_ROOT/app/helpers directory. It won't throw an error if it isn't there, but will warn you.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) In a standard setup, if you wanted to call a method before every page request (controller action request), how would you do it?

A) Add a before_filter call in the ApplicationController to the method you want do call. So, if your method was "check_for_permission", it would look like:

before_filter(:check_for_permission)

Note 1: This is assuming all your other controllers are descendants of the ApplicationController, hence the "standard setup" condition on the question.

Note 2: You can put this on any controller, not just the ApplicationController.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) If I include other modules in a controller why should I make the methods in the module either protected or private?

A) If you don't make the methods protected or private they will be accessible via the url, unless you have a security layer that prevents that access.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) When creating a partial, what's the naming convention?

A) Partials start with an underscore: _my_partial.rhtml

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) When calling render on a partial, how do you prevent a layout from being applied?

A) Pass :layout => false to the render call. It would look something like:

render(:partial => "my_partial", :layout => false)

Note: even though I use the name my_partial in my render call, Rails will look for a file named _my_partial.rhtml

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) What is the base directory for plugins?

A) RAILS_ROOT/vendor/plugins

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) For a basic plugin, in order for files in the lib directory to actually be loaded by rails what do you need to do?

A) You need to "require" the files in the init.rb file. If you have a file called string_ext.rb in your plugin lib directory, your init.rb would look like:

require "string_ext"

Note: I will probably post some plugin basics, nothing super tricky.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

I'm definitely going to have to categorize some other questions. Just too much to put under the RubyOnRails umbrella. So, yeah, there's more that could be added here. The first one will probably be a Migrations series of questions.

As usual, I'll add to this category of questions as I think of them.

Ruby Interview Questions - 101

Interview questions/answers for an entry level Ruby developer.
(Use these questions in conjunction with the 101 level Rails questions)

Q) How do you comment out a block of code?

A) Use =begin and =end.

=begin
def my_commented_out_method
end
=end

You could use successive # signs, but that's just tedious:
#
# def my commented_out_method
# end
#

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) How do you write to STDOUT in Ruby?

A) Actually two methods are available:
  • puts writes with a newline
  • print writes without a newline
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) What's the difference in scope for these two variables: @name and @@name?

A) @name is an instance variable and @@name is a class variable

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) What two delimiters are used for blocks?

A) Curly braces {...} and "do"..."end"

Bonus: coding convention is to use curly braces if the code will fit on one line and "do"..."end" syntax if the block contains multiple lines.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) How do you capitalize all characters in a string?

A) "this is my string".upcase

If the string is in a variable:
@my_string.upcase

Note: The method: upcase! is another alternative. See next question regarding methods that end with an exclamation.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) How do the following methods differ: @my_string.strip and @my_string.strip! ?

A) The strip! method modifies the variable directly. Calling strip (without the !) returns a copy of the variable with the modifications, the original variable is not altered.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) What is the naming conventions for methods that return a boolean result?

A) Methods that return a boolean result are typically named with a ending question mark.

For example:
def active?
return true #just always returning true
end

RubyOnRails Interview Questions - 101

Interview questions/answers for an entry level RubyOnRails developer:

Q) What site contains the Rails framework documentation?

A) api.rubyonrails.com

Note: When I was starting to learn Rails, there was always a tab open for this site. This is a guess that other developers learning Rails would be utilizing this page as well.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) What does RAILS_ROOT represent?

A) The base directory for your application.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) By convention, where are the images for the site stored?

A) RAILS_ROOT/public/images

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) Where do you put the database connection information?

A) A file named database.yml located in the RAILS_ROOT/config directory.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) List the directories located under the RAILS_ROOT/app directory.

A) controllers, views, helpers, models

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) By convention, if my model is named user.rb what will my table name be?

A) The table will be named users. Rails convention is to pluralize table names.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) What table is used to store the current migration version?

A) schema_info

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) What's the command used to run a migration?

A) rake db:migrate

Note: Here are a couple parameters I use often:
  1. --trace : outputs the process details to the screen. useful for debugging
  2. VERSION=<num> : set which version this migration should be targeting. needed to roll back your database.
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) Name some built-in validation methods.

A) Here's a list of the methods I use the most. The full list can be found on the api site.
  • validates_presence_of
  • validates_uniqueness_of
  • validates_length_of
  • validates_format_of
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) What is the helper method to generate an anchor tag?

A) link_to

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Q) If I have a controller file RAILS_ROOT/app/controllers/orders_controller.rb where would the orders index.rhtml file be located?

A) RAILS_ROOT/app/views/orders/index.rhtml


Intermediate (201) and Advanced (301) questions will be posted in the coming weeks. I'll also be updating this post as more questions come to mind.