Boban Jovanoski

Generating SHTML with middleman BobiYo Mar 11

4 comments Latest by Boban Jovanoski

Tags: shtml   frontend   middleman   haml  

Introduction

Because I wanted to improve my css skills, I've decided to spend time learning css, optimizations, the whole front-end development shebang. The latest project I worked on, the client required static web site done using SSI/Server Side Includes.

SSI/Server Side Includes ???

I knew it was something old, but I never touhght 15 years back :) as Rolad pointed that out. It is same as html but you can include content from other files (think of it as using partials in html). You can also use "bash scripting" syntax in your html, I have not look deeply into it, all I needed was to use shtml just for including content.

How to turn on SSI? Simply open your apache conf file and add +Includes in your apache options and add shtml to the known file types.

Options  +Includes
AddType text/html .shtml
AddOutputFilter INCLUDES .shtml

How to include content using shtml? It is very simple, the syntax that the includes module will recognize is almost the same as writing comments in html. Example: (notice there is no empty space before the #):

<!--#include file="includes/header.shtml" -->

It's middleman time

After creating your middleman project (how to create new project and how to use middleman, you can check on the middleman wiki), you need to setup middleman to generate shtml files.

Middleman already does this for you, so you'll just need to name your files ending with ".shtml.haml".

The next thing that you'll need to do is to make middleman insert the required shtml syntax to include content from other files (I've used this for header.shtml and footer.shtml which were put inside the includes directory). To do this, I've defined an alias for the partial method inside middlemans config.rb file.

alias_method :shtml_partial, :partial

When the content is build I've defined the shtml_partial method like this:

def shtml_partial(*args)
   "<!--#include file=\"includes/#{args.first}.shtml\" -->"
end

Wherever the shtml_partial method is used (same as partial) instead of rendering the partials content, it will generate the required shtml include content from file. But the files inside the includes directory don't exist yet?!! For solving this, on build time, I've just copied the partials files that are used inside the includes directory.

File.copy_stream("views/_header.haml", 'views/includes/header.shtml.haml');
File.copy_stream("views/_footer.haml", 'views/includes/footer.shtml.haml');

Hint - Remember to use relative links when building :)

activate :relative_assets

Happy using Server Side Includes in 2011 :)

Feel free to comment about new sugestions. Thank you in advance.

Haml, Compass, Front-end development BobiYo Feb 19

5 comments Latest by Guido

Tags: haml   scss   sass   compass   staticmatic  

Update

Thanks to Arthur Gunn I've checked out the middleman gem and by my humble opinion it is better than staticmatic, it is sinatra based and the helpers it provides are with the same names as in rails so you'll feel right at home. I still have not played with the frank gem, I'll update this post after I take a closer look at it.

Introduction - Staticmatic

During my recent work, I needed to create only the front-end (html, css, javascript) for an application. As you may guess, I've decided to use haml and compass, but creating a rails app for doing this seamed to me just like killing an alien with Justin Bieber's music.

Implementation

So I thought...there must be an easier way to to this (save the aliens)...so I did some research and discovered Staticmatic (all features are still not well documented).

gem install staticmatic

It's very easy to use. You just need to create your new staticmatic project:

staticmatic setup project_name

Compass and haml are supported, and a default layout is already setup for you to play with. All additional configuration for staticmatic and compass is done inside the config directory. Inside the compass configuration file I've only added

http_images_path = '/images'

because when css files are generated by compass the default directory is set to stylesheets.

If you wish to use other compass plugins like 960gs or whatever simply add the scss, sass files inside the src/stylesheets dir.

So now all you need to do is power up you favorite code editor, than start compass watch and the web server and start coding :)

#on separate consoles
compass watch 
staticmatic preview project_name

When you're done with that, you can generate the html with:

staticmatic build project_name

Explore the documentation how to use the layouts etc.

Things that I missed while using staticmatic

Features that I really missed and by my opinion need to be included are:

  1. Generating sprites for images - with the sprite_css or limonade gems

  2. yield :sidebar

  3. Using other gems :) I just wanted this usability to be implemented in staticmatic rather than hacking around and doing it manually.

Easier way?

I really like using haml and compass for front-end development, if you know a better way for doing this pls comment or email me, I'll be glad to update the post.

Some Tips And Tricks BobiYo Jan 28

Post a comment

Tags: rails   console   ubuntu   tip   trick  

List Rake Routes

rake routes | sed -e "1d" -e "s,[/]*,,g" | awk '{print $1}' | sort | uniq

Remove old kernel versions - Ubuntu

I'm using Ubuntu and RubyMine for developing ror apps and after some period of time after many ubuntu updates, I feel the need to remove old kernel versions :) and this is the command I use (10x @gemidjy):

sudo apt-get remove --purge `dpkg --get-selections 'linux-*.*' | awk '$2 == "install" { print $1 }' | grep -v "$(uname -r | sed 's/\(.*\)-.*/\1/')"`

Which process is using your port?

Sometimes you can't start a server/service because the port has been already taken? - In the example we search which process is using port 3000. You can check that with:

netstat -nlp | grep 3000 
#OR
fuser -n tcp 3000

List previous commands in rails console

While developing a rails app and meanwhile experimenting in the console :), sometimes you write a bunch of stuff which are chained and hitting the up arrow can sometimes be hurtful so using this command will show you a list of your previously entered commands:

puts Readline::HISTORY.entries.split("exit").last[0..-2].join("\n")

Use last result

After you execute some command in the console lets say User.first and you forgot to put it in a variable, instead of (up arrow, home, add variable name =) you can simply write:

user = _
# _ is the result of your last command :)

SQL to Rails Console

The simple way of doing this is after starting the rails console:

ActiveRecord::Base.logger = Logger.new(STDOUT)

If you want your console to be colorful and you can see all the db queries in all your rails project without writing this all the time after starting your console, you need to add changes to your .irbrc file in your home directory. I haven't added my .dotfiles on github yet...I'll update this post and set up a link after I do that :), meanwhile you can try putting this in your .irbrc file (It's old code that I found in my tips_and_tricks.txt file - email me or comment for an update I'll gladly change it. There is a gem for doing this but I forgot which one was the coolest).

script_console_running = ENV.include?('RAILS_ENV') && IRB.conf[:LOAD_MODULES] && IRB.conf[:LOAD_MODULES].include?('console_with_helpers')
rails_running = ENV.include?('RAILS_ENV') && !(IRB.conf[:LOAD_MODULES] && IRB.conf[:LOAD_MODULES].include?('console_with_helpers'))
irb_standalone_running = !script_console_running && !rails_running
if script_console_running
   require 'logger'
   Object.const_set(:RAILS_DEFAULT_LOGGER, Logger.new(STDOUT))
end

Routes In Console

To use routes methods in your rails console you need to include and set:

include ActionController::UrlWriter
default_url_options[:host] = 'whatever'

Listing controller routes

I got this tip from my friend Dalibor. You can list routes for a single controller by running:

rake routes CONTROLLER=projects

I hope that some of the tips help. Feel free to comment, add suggestions, etc.

Build Your Own Twitter Widget BobiYo Jan 20

Comments are closed

Tags: rails   twitter   widget  

Introduction

So, You've decided to create your own auto-updating twitter widget using rails? :) I won't bla bla what and why, let me just show you how I've done it: I've used the twitter gem and I didn't use rails's periodic updater for the tweets update :)

Implementation

  • Include the twitter gem in your Gemfile
  • Include and install jquery-rails gem
  • Add a loading gif image and your tweets container(the code for the views is haml).

= image_tag "loading.gif", :id => 'twitter_loading', :alt => "Loading", :style => "display: none"
#tweets_container

  • Map a route to controller/action by your choice, in this case services/twitter and you simply get the tweets

 #inside routes.rb
 match 'services/twitter', :to => 'services#twitter', :as => 'twitter_service' 

 #inside services_controller.rb
 def twitter
   @tweets = Twitter.user_timeline(USERNAME).first(NUM_TWEETS)
    render :layout => false
  end

 #inside twitter.html.haml
 - @tweets.each do |tweet|
   %p
     = auto_link tweet.text
     %span.time= link_to time_ago_in_words(tweet.created_at + ' ago' , "http://twitter.com/#{USERNAME}/status/#{tweet.id}"

This was easy :) now all we need is to show and auto-update the widget. So in your application.js or a js file that is loaded in your page :)

var twitter = {
    container: $('#tweets_container'),
    loading_image: $('#twitter_loading'),
    update_interval: 420000, //7 minutes
    clearTimeout: function() {
        if (this.timer_id) {
            clearTimeout(this.timer_id)
        }
    },
    autoUpdate: function() {
        var self = this;
        self.clearTimeout();
        self.timer_id = setTimeout(function() {
            self.initialize();
        }, self.update_interval);
    },
    initialize: function() {
        var self = this;
        self.clearTimeout();
        if ($('#tweets_container').size() > 0) {
            $.ajax({
                type: 'post',
                url: "/services/twitter",
                data: {},
                dataType: 'html',
                ifModified: true,
                beforeSend: function() {
                    self.container.hide('slow');
                    self.loading_image.show('fast');
                },
                success: function(data, status) {
                    if (status != 'notmodified') {
                        self.container.fadeOut(1200, function() {
                            $(this).html(data);
                            $(this).fadeIn(1200);
                        });
                    }
                    self.loading_image.hide('fast');
                    self.autoUpdate();
                },
                error: function() {
                    self.loading_image.hide('fast');
                    self.autoUpdate();
                }
            });
        }
    }
};
twitter.initialize();

That's it, I hope this helps :) Your comments and suggestions are welcomed.

Standalone Widgets BobiYo Jan 14

Comments are closed

Tags: widget   apotomo   javascript   jsonp   rails   ruby  

Introduction

For a not so much recent project I needed to create a standalone widget that can be displayed on any page with less effort. You can see the result here (don't forget to view source). And if it seems interesting to you, keep on reading :) As far as I know this can be done with iframe or javascript(jsonp), if you know any other way pls let me know.

alt text

The Idea is to create a standalone widget for your application that can be used easily on any other site. Think of it as minifying your app where cool stuff are happening :) So I did some research and I've decided to use pure javascript and Apotomo, because:

  • Fun

  • Apotomo - which separates the stuff that you need and you get a much cleaner code, hence the speed. Apotomo comes with many othercool stuff, I recommend that You check out the tutorials http://apotomo.de. I'll explain later why I've decided to use Apotomo :)

  • Javascript - I got a bit nostalgic for writing pure js....and using a framework may have conflicts with the clients js, and widgets need to be independent. The js that is used is inspired from the twitter widget.


Implementation

Create new rails 3.0.3 app - there is an issue with json serialization in previous rails versions, the to_json method does not return the required structure.

  1. Add haml+compass in your Gemfile :)
  2. Create new apotomo widget with

    rails generate apotomo:widget apotomo_widget display_form --haml

  3. Create/Use the models from your application so you can get the data that you want to show in the widget. I've created a simple PostLink model that has title and url. There is also a rake task that gets the titles and urls from apotomo's feed and stores them in db.

  4. Set up the widget display action - see source in haml.

After the display action for the widget is defined we can add some styling, but we also want the client to be able to set a theme for our widget. At first, I've defined different css for every theme that is used when the widget is initialized, but I've depricated that code and I've decided to put all the styling for different themes in one file. My css skills are .... :) anyway you can check the styling for some themes that I've set here


It's js time

Ok, we've set the display action for the widget, now it's time to create a widgets controller and write some js, so:

  • Create a widgets controller that responds to the index action with js
  • set: match "widgets", :to => "widgets#index" in routes.rb
  • Create index.js.erb in app/views/widgets directory.

class WidgetsController < ApplicationController
  include Apotomo::Rails::ControllerMethods
  has_widgets do |root|
     root << widget(:apotomo_widget, 'apotomo_widget', :display)
  end

  def index
     respond_to do |format|
      format.js
     end
   end
end

You can check the end result here. At first I've defined some helper methods that are used through the code. JsonP is used for getting data from the server..css and data that we want to display. Every widget has it's own istance which is known by the widget_number, and it's own refresh_interval. For this example I've added options for refresh_interval and theme to be set by the client.

After the widget is initialized the autoRefresh() function is called which updates the widget data. So how do we get the data from the server?

This is the why apotomo part kicks in....despite the number of widgets that we can create using Apotomo, all apotomos widgets will respond with the action that we've requested: so for example if we have lets say 3 apotomo widgets (first_widget, second_widget, third_widget) they'll all respond to /widgets/render_event_response action where as arguments we specify on which widget(source), which action(type) we want to call.

In this example: we request for: &source=apotomo_widget&type=update This will call the update action in apotomo_widget...which we use to execute our callback.

def update
  text = params[:callback] + '(' + PostLink.all.to_json + ')'
  render :text => text, :content_type => 'application/json'
end

Unfortunately Apotomo does not accept the :callback parameter :( ...usually the rails way we simply need to call:

render :json => PostLink.all, :callback => params[:callback]

The callback parameter in this example looks like this APOTOMO.Widget.updatePosts_1 for the first widget instance, APOTOMO.Widget.updatePosts_2 for the second widget instance and so on. So this methods are executed in javascript which updates the widget data for the widget that requested


At the end

Now all that we need to do is to include our js(path to our widgets/index action) on any page and create the widget/widgets instances. This can be done on any web page, all that needs to be entered is:

<script type="text/javascript" src="http://widgets.jovanoski.net/widgets"></script>
And where we want the widgets to show we simply put
<script type="text/javascript">new APOTOMO.Widget({refresh_interval: 800000, theme: 'default' });</script>
<script type="text/javascript">new APOTOMO.Widget({refresh_interval: 800000, theme: 'blue' });</script>