Posts Tagged Rails

MongoMapper callbacks/hooks

It took me a while to find these, so I thought I would post them here. In the end I had to search the source code to find them.

:before_save,                        :after_save,
:before_create,                      :after_create,
:before_update,                      :after_update,
:before_validation,                  :after_validation,
:before_validation_on_create,        :after_validation_on_create,
:before_validation_on_update,        :after_validation_on_update,
:before_destroy,                     :after_destroy,
:validate_on_create,                 :validate_on_update,
:validate

I was searching for these amongst MongoMapper doucmentation and blog posts when really they are an ActiveSupport concept as the following comment suggests:

Almost all of this callback stuff is pulled directly from ActiveSupport . . .

Being new to rails I wasn’t very familiar with the ActiveSupport stuff and so I didn’t know to look there. Anyway this is how I use them in my posts model:

class Post
  include MongoMapper::Document

  many :comments

  key :title, String, :required => true
  key :slug, String
  key :body, String, :required => true
  key :published, Boolean
  key :published_on, Date, :default => Date.today

  after_save :update_comment_titles

  private

    def update_comment_titles
      comments.each do |comment|
        comment.post_title = self.title
        comment.save
      end
    end

end

My comments live in a separate document collection and each Comment document contains the title of the Post that it belongs to. This allows me to list all comments (on the admin page for example) without having to query any of the Post documents.

This above after_save call back ensures that the post_title on each Comment is updated if I ever update the title of the post.

Tags: , , , ,

Inversion of Control, Two Ways

One of the reasons I like to play with other languages from time to time is to find new ways of solving problems. This is why, while learning Ruby on Rails, I am making a conscious effort to do things the Ruby way, as opposed to writing C# style code in Ruby.

While working on my new blog page, I encountered a problem that was identical to one I had on a previous project but using ASP.Net MVC. In both projects (but for different reasons) I made a design decision to use Amazon’s S3 web service for storing images. However, I wanted the option of switching to an alternative local (file system based) implementation at configuration/deploy time.

The ASP.Net MVC way

The C# solution to this problem was obvious to me at the time, because I was already using an Inversion of Control container. I created two implementations of my image repository and set up the IoC container to use whatever implementation I wanted based on some configuration setting (note: In this extract I am also setting up local/remote message queue implementations):

if (bool.Parse(ConfigurationManager.AppSettings["RunLocal"]))
{
   _container.RegisterType<IBinaryRepository, Local.BinaryRepository>(
       new InjectionConstructor("F:/TadmapLocalData/LocalBinaryFolder")
   );

   _container.RegisterType<IMessageQueue, Local.MessageQueue>(
      "Image",
      new InjectionConstructor("F:/TadmapLocalData/LocalImageMessageFolder")
   );
   _container.RegisterType<IMessageQueue, Local.MessageQueue>(
      "Complete",
      new InjectionConstructor("F:/TadmapLocalData/LocalCompleteMessageFolder")
   );

   _container.RegisterType<FileUploaderAdapter, LocalUploadAdapter>();
}
else
{
   _container.RegisterType<IBinaryRepository, Amazon.BinaryRepository>(
      new InjectionConstructor(
         ConfigurationManager.AppSettings["S3AccessKey"],
         ConfigurationManager.AppSettings["S3SecretAccessKey"],
         ConfigurationManager.AppSettings["S3BucketName"]
      )
   );

   _container.RegisterType<IMessageQueue, Amazon.MessageQueue>(
      "Complete",
      new InjectionConstructor(ConfigurationManager.AppSettings["CompleteMessageQueue"])
   );
   _container.RegisterType<IMessageQueue, Amazon.MessageQueue>(
      "Image",
      new InjectionConstructor(ConfigurationManager.AppSettings["ImageMessageQueue"])
   );

   _container.RegisterType<FileUploaderAdapter, DirectAmazonUploader>(
      new InjectionProperty("BucketName", ConfigurationManager.AppSettings["S3BucketName"]),
      new InjectionProperty("AccessKey", ConfigurationManager.AppSettings["S3AccessKey"]),
      new InjectionProperty("SecretKey", ConfigurationManager.AppSettings["S3SecretAccessKey"]),
      new InjectionProperty("FileAccess", com.flajaxian.FileAccess.Private)
   );
}

The Ruby on Rails way?

While looking for an IoC container or equivalent Dependency Injection framework, I started to realise that although DI frameworks exist for Ruby they are normally not used. One of the articles I read suggested reopening the class and mixing in a module. So I gave this a try.

Most of my models are including a module to define the persistence implementation, for example my Post class is stored as as mongoDB document:

class Post
  include MongoMapper::Document
  # ...
end

So my first step was to move all image persistence code into two different modules, one for S3 storage and one for local file storage.

Then inside an initializer file, I check my configuration and based on this, I reopen the class and include the appropriate persistence module:

require 'image'

IMAGE_STORE_CONFIG = YAML.load_file("#{RAILS_ROOT}/config/image_store.yml")[RAILS_ENV]

if IMAGE_STORE_CONFIG['use_s3']

  class Image
    include S3ImageStore
  end

else

  class Image
    include FileImageStore
  end

end

This solution works for now, although I am not entirely happy with it. My problem is that my Image model now looks like the following:

class Image

   attr :name

end

This is very simple (which is good) and there are no details about it’s persistence (which is also good), but it doesn’t give the reader any clue that it can persist itself. For example, in C# I would have to have a placeholder (interface) for my implementation that would indicate to the reader that there is some stuff missing and this is what the missing stuff would look like if you want to go looking for it.

I am happy now that I can easily switch between cloud services and local implementations, but I can’t help thinking there is a better way of achieving this…

Tags: , , ,

A new blog and learning Ruby on Rails

My blog has been a Word Press application for a while now but two things have been bothering me.

  1. I spent ages playing with the application settings and server settings to try and get the URLs the way I wanted, they are still not what I want. Nothing complex, I justed wanted a little more control.
  2. There are thousands of plugins that do almost what I want, but none that do exactly what I want. Most are customizable but sometimes you end up having to hack some PHP.

As a web developer, I am used to having full control over my URLs from within the code and would like to tweak the behaviors using the tools and languages I am familiar with.

My original idea was to write a new blog application using ASP.Net MVC, but have since decided to use this as an opportunity to learn something new.

I’ve been spending a lot time recently learning a new language and framework, namely Ruby on Rails. At first it was just to see what all the hype was about but I eventually got hooked. Right now I am in the middle of developing my new blog/website using this fantastic framework.

I’ve already blogged about some of the new stuff I’m learning (Checking page titles with Cucumber) and I will probably have some more posts about it before it goes live.

Tags: , , ,

Checking page titles with Cucumber

As a way of learning a new framework I started to write my own blog application using Ruby on Rails. I’ve also taken the opportunity to try a bit of BDD using Cucumber, which I’m finding is a lot of fun. One feature that I have written recently and particularly like is:

Feature: Main Title
  In order to improve SEO and help readers know what they are looking at
  The reader or search engine spider will need the name of the page
  and the author's name in the title of all pages

  Background:
    Given I have a post with title "Why I really like Ruby"

  Scenario Outline: Pages contain name and author in the title
    Given I am on the <Page>
    Then I should see "<Full Title>" within "title"
    Examples:
    | Page                          | Full Title                            |
    | home page                     | Home - Trevor Power                   |
    | about page                    | About - Trevor Power                  |
    | contact page                  | Contact - Trevor Power                |
    | blog page                     | Blog - Trevor Power                   |
    | "Why I really like Ruby" post | Why I really like Ruby - Trevor Power |

This test is very simple, it visits each page in the listed examples and checks that the title is as expected. For me it is important that this is tested automatically because as developer/tester of the site I never really pay attention to the text that appears in the window title. But this text is important for search engines as well as appearing in browser history and book marks.

Another thing I like about this test is the cross cutting nature of it. The titles of all pages from different parts of the website are listed together and any inconsistencies are made obvious.

I don’t have syntax highlighting on this blog for gherkin (the language used in the above spec) but here is a screen shot of the results which might be more readable:

Screen shot of the Cucmber results for the above feature

Tags: , , ,