August 09, 2010

Rails, Ajax and Exceptions? Bring it on.

Recently I’ve been working on a content management system that’s very Ajax heavy. I think Ajax is great, but if your request raises an exception you’re going to get some unexpected results. In the case where your Ajax request is expecting a JavaScript response to evaluate the enduser will sit there with no response and no indication of an error. We can do better than that.

If your application uses Ajax in two or three places, it’s not hard to code for those specific use cases, but what about three or four instances per page? We’ll need to DRY this up.

Read the rest of this entry

June 25, 2010

Application Settings through ActiveRecord

After a few side projects I’ve noticed that I’d use this approach for a settings object pretty often. My settings table is very basic, just two columns, name and value. The magic happens inside the Settings model.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# app/model/settings.rb
class Settings < ActiveRecord::Base
  class << self
    def setup
      return if @settings
      @settings = {}
      all.each { |s| @settings[s.name.to_sym] = s.value }
    end

    def [](key)
      setup
      @settings[key]
    end
  end
end

I gave myself a setup method that cycles through every entry in my settings table and stores them in the @settings hash. Notice I call return if @settings is defined because there’s no need in rebuilding @settings. Next, I define the [] method to make the model act like a hash. Inside the [] method I return the value @settings at the position of the provided key.

It allows me to do stuff like this:

1
2
puts Settings[:name]
puts Settings[:version]

It’s really simple, but I like it. What about you?

June 21, 2010

Rake Tasks 102

This is a follow up post to Rake Tasks 101. In the 101 post we created Rake tasks, setup dependencies and made our tasks reusable by passing in parameters. In Rake Tasks 102 we’ll be building on those practices, interfacing with a Rails environment and leveraging the cron to automate our Rake task.

Read the rest of this entry

June 06, 2010

Rake Tasks 101

I’ve been working with Rake quite a bit on my current project so I thought I’d share some beginner tips.

Before I go into Rake, what is it? Rake is a Ruby-based build program. Ruby on Rails uses Rake quite a bit in it’s process. If you’ve worked on a Rails project you’ll used one, some or all of the following: rake db:create, rake gems:unpack, rake db:migrate, and rake test. Now that’s not all of Rail’s Rake tasks, just some common ones.

You’re here to make your own Rake tasks so lets get started!

Read the rest of this entry

May 11, 2010

RVM, Ruby 1.9 and Rails 3, you complete me

I finally got around to install RVM, Ruby 1.9 and Rails 3. I ran into some issues the first time I installed RVM so this time around I documented every step I took. When reading this post, please assume I am logged into the system as the default user unless I indicate otherwise.

Installing RVM the way I’m told

On the RVM install page it recommends to install from the Github repository. Wayne was even nice enough to give a series of chained commands to copy and run:


mkdir -p ~/.rvm/src/ && cd ~/.rvm/src && rm -rf ./rvm/ && git clone --depth 1 git://github.com/wayneeseguin/rvm.git && cd rvm && ./install
Read the rest of this entry

December 29, 2009

Magnetism as an integrated system or independent?

Before I get started, I haven’t gotten to Liquid filters like I had planned. Thats still on the way. Instead, I’ve been banging my head to decide what is the best approach to take for the administration portion of a blog/CMS.

Integrated System

When I say an “integrated system” I mean a system that lays on top of the existing site, a toolbar. This is a very basic wireframe of the concept.

This approach can be very friendly because it’s your site, but with tools. The website and the admin panel are mixed. If I continue down this road the website has to be built in order for the admin panel to be accessible. Data can’t be entered into a site that isn’t built. Going this route also means the developer has to be CSS conscious. Using !important in CSS would be at the top of my list of “No-Noes.” These are two large issues I see with this kind of system.

Independent System

An independent system would exist completely separate from the website. The views would not mix. This creates a major disconnect from the content entered and the design of the website. On the brighter side, that disconnect removes the need of building the website first and potentially conflicting CSS. I think I’ll continue with this approach.

Now I need to layout the dashboard page, the first page you see after logging in. Before I start pretending to be a designer I need to figure out what I need and what I want to appear on this dashboard. Once I login I want to be one click away from entering new content. The content I’m entering could be a blog post, a conversation, a quote, an image or video or a code gist for the programmers out there. I will also want to see whats been happening with my site. Have content entries been added, modified or commented on? This is information I’d like to see.

Those are some ideas. It’s time to get started on the sketches. More on that as it comes.

December 07, 2009

It has Liquid::Blocks and it's called Magnetism

In my previous post about Liquid I never gave my project a name. Today it’s called Magnetism. It’s a pretty cool name for something that doesn’t work yet. I’ll be writing about Liquid assuming the audience is aware of what it and the Liquid syntax. Liquid consists of a few pieces. There are filters, drops, tags and blocks. This post will be going over blocks. Future posts will go over the other elements of Liquid as I add them to the Magnetism project.

What is a Liquid::Block

Liquid comes with a few blocks by default. You have if, unless and for to name a few. These wrap around template content.

1
2
3
4
5
6
7
8
9
10
11
12
<!-- the if block -->

{% if this_case %}
  do something in here.
{% endif %}

<!-- the for block -->
<ul>
{% for element in elements %}
  <li>{{ element }}</li>
{% endfor %}
</ul>

The prepackaged blocks are essential for template development, but I needed a few more so I dug through the Liquid documentation and the source code and got my hands dirty. I store my blocks in RAILS_ROOT/lib/magnetism/liquid and register them in RAILS_ROOT/config/initializers/magnetism.rb, but more on that later.

I’ve packaged my blocks in Magnetism::Liquid, but this isn’t necessary. This is how both cases would look.

1
2
3
4
5
6
7
8
9
10
11
12
13
# packaged
module Magnetism
  module Liquid
    class HTML < ::Liquid::Block
      # ...
    end
  end
end

# not packaged
class HTML < Liquid::Block
  # ...
end

The difference is at the line of inheritance. In my packaged class Liquid::Block is prefixed with ::, but that isn’t necessary in the second example because the class is not packaged. When creating a Liquid block two methods are called. There is the initialize method and render. At the moment I only needed render.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# lib/magnetism/liquid/html.rb
module Magnetism
  module Liquid
    class HTML < ::Liquid::Block
      def render(context)
        return <<-EOF
<!DOCTYPE HTML>
<html>
#{super}
</html>
        EOF
      end
    end
  end
end

The render method always has Liquid::Context passed into it. Even though I’m not using context in my render method I still needed to define it so render wouldn’t error. Within render the super method returns any code contained in your custom block.

1
2
3
4
5
6
<!-- index.liquid -->
{% html %}
<body>
  <h1>My Liquid Template</h1>
</body>
{% endhtml %}

This isn’t all Liquid blocks can do, but that’s all I’ve needed for Magnetism thus far. I’ll revisit Liquid blocks and explain Liquid::Context when I work on the comments form. Stay tuned for more!

December 05, 2009

Rendering Liquid templates from outside the views directory

Today I’m working with Liquid in Rails. I’m setting up a theme system for this project so I decided to store the liquid templates in RAILS_ROOT/app/themes. With all of that said, lets start from the beginning.

First add the Liquid gem to the environements.rb file.

1
2
# RAILS_ROOT/config/environments.rb
config.gem "tobi-liquid", :lib => "liquid", :version => ">= 2.0.1", :source => "https://gems.github.com"

Next unpack the gem with: rake gems:unpack. That will add the gem to vendor/gems. At this point you can render liquid templates within the app/views directory, but not outside of the views. You can test this by creating some controller and replacing the view’s .html.erb extension with .liquid and tell the controller to render the liquid template: render "your_file.liquid"

I’d like to render liquid templates that exist in app/themes so I did the following: render "#{RAILS_ROOT}/app/themes/default/templates/index.liquid" Instead of rendering the template like I expected, my browser downloaded the unprocessed liquid file. This is all handled with ActionView. I don’t know why ActionView will only render liquid templates within the app/views directory, but it will render regular .erb files from anywhere.

The solution was very simple after looking over the Liquid’s LiquidView documentation. I just had to tell ActionView to handle liquid files with LiquidView! This documentation is just old enough to not work anymore. ActionView::Base::register_template_handler was available at that location until version 2.1. It is now ActionView::Template.register_template_handler.

Finally make a liquid.rb file in config/initializers, require the extras/liquid_view path and register LiquidView to handle liquid templates. It should look like this:

1
2
3
4
# RAILS_ROOT/config/initializers/liquid.rb

require 'extras/liquid_view'
ActionView::Template.register_template_handler :liquid, LiquidView

Ta-da! Now you can render liquid templates from any location!

November 29, 2009

Authlogic, RSpec and :priority_record=>nil... wtf.

I think Authlogic is great. I think RSpec is great, but damn did I ever give myself a confusing error. My view specs were passing so I moved onto the controllers. The controller specs passed so I moved onto the models. After the models passed I tested all of the specs and found that I had broken the controllers some how.

When running my SessionsController tests I’d get an error like this:

1
2
3
<UserSession (class)> received :new with unexpected arguments
  expected: ({:password=>"valid-password", :login=>"dane"})
    got: ([{:priority_record=>nil}, nil])

At other times I’d get:


Mock "UserSession_1050" received unexpected message :priority_record= with (nil)
Read the rest of this entry

October 28, 2009

Ajax responses with Rails partials

I was working on a Rails app last night and hit a problem. I thought I’d share the problem and solution.

I had a form process an Ajax call on submit and evaluate the response text. I use jQuery so keep that in mind when you read the example JavaScript code.

1
2
3
4
5
6
// main.js
$('form[data-remote=true]').submit(function(){
  $form = $(this);
  $.post($form.attr('action'), $form.serialize(), false, 'script');
  return false;
});

You’ll notice the “data-remote=true” part. Disregard that. It’s just something coming down the pipes in Rails 3. So the JavaScript works. My controller works and renders the appropriate view.

1
2
// update.js.erb
$('#entries ol').append('<%= render(:partial => "entries/item", :locals => { :entry => @entry, :list => @list }) %>');

Thats the view rendered by the controller. You’ll see the view renders a partial within it.

1
2
3
4
5
6
7
8
<!-- entries/_item.html.erb -->
<li class="entry<%= cycle('', ' alt') %>" id="entry-<%= entry.id %>">
  <menu>
    <li><%= link_to "Update #{entry.name}", list_entry_path(list, entry), :class => "update" %></li>
    <li><%= link_to "Remove #{entry.name}", list_entry_path(list, entry), :class => "destroy" %></li>
  </menu>
  <p><%= entry.name %></p>
</li>

Well everything looks pretty good, but I kept getting the JavaScript error “unterminated string literal.” This is due to the line breaks in the entries/_item partial.

1
2
3
4
5
6
7
8
// will work
$('#entries ol').append('<li>\n\tThis is a new line\n\tThis is a second line\n</li>');

// this will not work
$('#entries ol').append('<li>
  This is a new line
  This is a second line
</li>');

To fix this I modified my update.js.erb view slightly. I added gsub("\n","").

1
2
// update.js.erb modified
$('#entries ol').append('<%= render(:partial => "entries/item", :locals => { :entry => @entry, :list => @list }).gsub("\n","") %>');

After pulling out the line breaks the JavaScript error disappeared. Hope this helps!

October 09, 2009

The RSpec Book

I recently finished The RSpec Book, well as much as you can finish a book in-progress. The RSpec Book is just great. It starts by explaining RSpec and Cucumber for Ruby applications and later progresses into BDD for Ruby on Rails. It’s a must read for anyone that wants to learn RSpec.

September 26, 2009

jQuery, me and form validation

Whether they know it or not anyone that has used the internet has experienced form or content validation. The purpose of content validation is to preserve the integrity of the application or service. Entering “100” as your first name wouldn’t make much sense. Trying to email “ABC-123?” wouldn’t make sense either. To prevent this from happening we can validate content in all sorts of ways, but the most important thing to remember is define what you will allow and not what you wont. For the examples to come I’ll be using the lovely Mary Jane Watson.

On the web there are two locations were validation can happen, on the server or in the browser. The application receives the content and validates it to determine whether to perform the next action or not. This is server-side validation. There is also client-side validation, handled by the browser. This is approach is done with JavaScript. Server-side validation is required, but client-side validation isn’t. Even though client-side validation isn’t required I can think of more reasons to do it than not. From a usability standpoint client-side validation is excellent. The user should receive feedback indicating whether or not content entered is allowed. Twitter does this with their sign up form as you type. Facebook gives feedback after you hit submit. Both are acceptable approaches. It also reduces the load on your server. By checking the user’s content before sending it to the server reduces the amount of work your server has to do. This is great because the server can spend those unused resources elsewhere. So now that we’ve seen two real world examples and understand the server benefits let’s get started validating with JavaScript.

Read the rest of this entry

September 02, 2009

Netflix, you had me at hello

I love Netflix. They provide an excellent service, a simple system and they stream a handful of their movies! I’ve heard complaints about Netflix, but when I think about it… I have none. The other evening I received an email that just reenforces why I am a very happy customer.

Netflix Email

They aren’t waiting for me to contact them saying I have a problem. They’re making the effort and contacting me saying, “Hey we had a little problem. Did it affect you?” They’re trusting me to redeem the credit if I was in fact affected by the technical issue. Who else does that?

Way to go Netflix team! I had no reason to leave, but I have yet another reason to stay.

August 12, 2009

fields_for in Rails, but no one mentions it (part 2)

Just an addition to my previous post on using fields_for.

A second approach to the same issue of working with the params data would be to utilize the attr_accessible method in the model.

1
2
3
class Page < ActiveRecord::Base
  attr_accessible :name
end

Using attr_accessible indicates what values of the model can be mass assigned. That I’ve only set :name, no attempt will be made to write the content portion of params. You can simply do the following:

1
2
3
4
5
6
7
@page = Page.new(params[:page]) # create the page
content = @page.contents.build(params[:page][:page][:content]) # create the content

if @page.valid? and content.valid?
  @page.save
  content.save
end

Both approaches work, but this will keep the controller clean.

August 09, 2009

fields_for in Rails, but no one mentions it

I was laying out a form for a page model last night. Each page has_many :contents. That’s straightforward enough, but when it came to the view I wanted to present the fields from page and the associated content model. That way the user can enter all of the necessary content, for both models, on a single page.

The Rails API explains fields_for very well, but there is no information on how the controller should act. I couldn’t find anything on the controller aspect anywhere. So this is what I’ve come up with.

The posted form looks like this.
1
2
3
4
5
6
params = {
  "page" => {
    "name" => "My Sweet Page",
    "content" => { " block"=> "This is why my page is so sweet" }
  }
}

You can’t just throw params[:page] into the Page model and save it because that will fail. It fails because content is an associated model and does not exist in the page table.

1
2
@page = Page.new(params[:page])
@page.save! # fails here

What you’ll need to do is remove the content data from params before adding it to Page, but make sure you hold on to it so you can create the content block.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
params_content = params[:page][:content] # get page content
params[:page].delete :content # remove content from page

@page = Page.new(params[:page]) # create the page
content = @page.contents.build(params_content) # create the content

if @page.valid? and content.valid?
  @page.save
  content.save

  flash[:notice] = "Your page has been sucessfully created."
else
  flash[:error]  = "There was a problem with the content you've entered."
end

This approach works pretty well. Alter the code to fit your needs, but this should work well enough for a prototype.