Friday, November 20, 2015

Using SendGrid Categories in Rails Action Mailer


I wanted to start using the categories feature on SendgriD
in my Rails app but they didn't document a way to do that in Rails.
So here's how I ended up implementing the categories, hopefully this will save someone some time.


Let's say you want to track clicks and opens for each and every email you send out through Rails, and let's also assume you are using SendGrid.
SendGrid has a feature called "categories" that was designed for this purpose.

First off go to your SendGrid settings and under the "Tracking" tab make sure you have clicks and opens enabled.


After that's done we can start changing our Rails code.


Simple Way:

If you only have a couple of emails in your app then there is no need to over complicate things
and you're in luck
add this line to your method, before the mail call:

headers['X-SMTPAPI'] = '{"category": "User welcome"}'

This will add the X-SMTPAPI header that SendGrid is expecting. 
The category key can actually except an array incase you want to use multiple categories per email. 

You'll end up getting something like this:


class UserMailer < ActionMailer::Base
    def my_message(name, email)
       @name = name
       @email = email
       headers['X-SMTPAPI'] = '{"category": "User welcome"}'

       mail(:to => @email,
            :from => me@me.com,
            :subject => "Welcome!")
    end
end

And that's it! you're done!

But... if you're anything like me you probably have several mailers and a growing amounts of emails. It will really get annoying to have to remember to always add that header line just so you'll have statistics for that email.

Generic Way:

If you have multiple mailers I recommend starting off by creating a base class like:

class BaseMailer < ActionMailer::Base

end

Then simply make all your mailers inherit this new class

class UserMailer < BaseMailer

end

After you have this setup the categories solution is in reach.
Create a before filter in the base class,
get the method's name,
add the header with that name

* note: If you're not on Rails 4 but on Rails 3 you'll have to add:
include AbstractController::Callbacks
To your base in order to have support for callbacks.

class BaseMailer < ActionMailer::Base
  include AbstractController::Callbacks # only for Rails 3

   before_filter :add_sendgrid_header

  def add_sendgrid_header
     category_name = action_name.gsub("_", " ").capitalize
     headers['X-SMTPAPI'] = {category: category_name}.to_json
  end
end

And that's it, the name of the actions will be sent as the category and you won't have to worry incase you add more emails.



Not using SendGrid and need email analytics for Rails?

checkout this cool gem:

https://github.com/ankane/ahoy_email



Monday, October 22, 2012

Getting started with Ruby On Rails

I have been an ASP.Net developer for 6 years and in the last year or so I have been working only on ASP.Net MVC, I truly think its great! And much better then ASP.Net.

but... I had the need to learn something new and open source, have a little diversity and stop being just a "Microsoft developer" which is pretty common in Israel... anyway I choose Ruby On Rails 3 which looked very cool, and of course its MVC too so I knew it will be easier for me.

I will describe the step by step process I have taken in order to move to rails.

Part One - OS!


Lets choose an operating system, after a bit of reading (thank god for stackoverflow.com) it was clear that the natural environment to develop Rails is a mac, but i don't have mac and i am not a big fan of Apple in anyway, but I do have experience with Linux, so I decided to go with Linux.
It really doesn't matter, plenty of rails developers are using Linux...
So the first step will be to download Ubuntu 12 installer.
It's not like the old days where you had to re partition everything and format and have a crappy GUI for the install process only to find out in the end that it didn't work.
Today Ubuntu offers a cool installer which will install Ubuntu side by side
with your windows. download ubuntu installer this is pretty easy and i don't have much to say about it. Just install it! Then restart your computer and you will be able to choose if you want to go into your Linux or windows. (very nice...)
Choose Linux of course! If its your first time on Linux don't worry you are going to love it!

Part Two - Installation!

Now that Linux is up and running its time to install
Ruby and Rails (rails is a gem for ruby)

First things first, open the terminal (you can just press the win-key and type terminal) never close the terminal, you will use it all the time.






Ubuntu has a tool called APT and you can use it to install and manage applications.
Lets first update it. To do so, run this command: sudo apt-get update
(sudo is the command for running commands as the root user so it will ask for your root pass).
After the update we can begin with the install. If you will google installing rails on ubuntu you will get this page in the ubuntu site its really out dated and talks about ubuntu 9 and installing rails and gems with APT. This is highly not recommended, so i found this post: 
better simple post that explains how to install ruby, rails, gems on ubuntu

Tthese are the steps you must take:
  1. Install curl
  2. Install RVM
  3. Install all the libraries mentioned
  4. Install ruby
  5. Install rails
  6. and stop!

Now its time to talk about databases.  Usually rails development can be done with sqlite or MySQL but because I choose to work with heroku (later on i will explain why) I choose to work with PostgreSQL.  You can install MySQL too but be sure to install PostgreSQL


install guide for PostgreSQL 
Run this command as well :
sudo apt-get install libpq-dev
Be sure to install pgadmin3 so you can manage your database later on with a nice GUI. so like before: sudo apt-get install pgadmin3
to open pgadmin3 just go to your dash home and find it there or type pgadmin3 in your terminal.


Any problems?
When I tried to install the rails gem i got this error: "It seems your ruby installation is missing psych (for YAML output)" I fixed it by following this  question on stackoverflov.
The fix is 3 easy commands for you to run in your terminal: 
cd ~/.rvm/archiveswget http://pyyaml.org/download/libyaml/yaml-0.1.4.tar.gzrvm reinstall 1.9.3

Now you can try an run gem install rails again and this time it should be fine (do it from your home directory, type cd then just enter)

Part Three - IDE!


We now have new OS, Ruby On Rails and PostgreSQL, time to install an IDE so we can start coding!
As ASP.Net developers we are used to the amazing Visual Studio, but its time to learn something new.. So lets choose an IDE
In the mac rails developers use TextMate and on ubuntu some use Gedit with a customization called Gmate, tried it for a few days... didn't like it. I am used to a full a feature IDE so the solution is called Netbeans! This is discussed on this thread so Netbeans is really nice, lets go ahead and install it, run: sudo apt-get install netbeans . Netbeans doesn't come with built in Ruby support (anymore) we must install it as a plugin. 
  • Open netbeans (to open Netbeans just go to your dash home and find it there or type Netbeans in your terminal) and go to: tools -- > plugins
  • In the plugins window go to settings tab and on the left check Plugin Portal
  • Then go to the Available Plugins tab and press Reload Catalog then you can do a search on the right for "ruby".
  • Check the checkbox for the ruby and rails plugin and click install. 
  • Netbeans will restart and you will have Nebeans with Ruby.

To try it out you can just create a test app, and open it with Netbeans.
  • You can try it out now. in your terminal run: rails new testapp.
  • Then run cd testapp followed by: bundle install .
  • Your test application is ready to go. 
  • Open Netbeans and click on new project.
    In the categories on the left click Ruby and on the right choose 
  • Ruby on Rails application with existing sources 
  • give your project a name and browse to find your testapp directory in your home folder. 
Your first rails project is now loaded in your IDE. You can start coding in Rails!


Part Four - Learn Rails



Everything is setup, now its time to start learning and coding Ruby On Rails.
So grab this excellent book: Rails 3 in action
and start seeing all these great video casts at: railscasts.com 
Another great resource is: Rails guides.
I started with these three but also thought of an app to build and just started building it. there is no faster way to learn then to just get your hands dirty in the code and start running into problems, so you can solve them.



Part Five - Deploy


By now you surely want to just get started and upload your first site. but how?.. and where? One of the popular places to host your rails apps is on heroku.com which is a cool cloud application platform, with addons you can install at a click of a button. You can sign up for an account which gives you 5 free repositories for your apps. If you are just experimenting you can keep it as a free account, but if you plan on building a full app with lots of traffic... Well.. that's when you start paying.
So heroku is very easy to work with and very well documented with lots of helpful tutorials. Just read through there dev center devcenter.herouku.com and you will be fine.

Uploading your code is as easy as writing: git push heroku master
I like it. plus even with a free account you can add your own domain names.
Your heroku account will have PostgreSQL set-up right out of the box. and that's why we installed it. You can still keep your development environment on sqlite but I prefer my development environment the same as my production one so I use Postgre in my local machine as well. (this is also the recommendation from heroku) you will notice how easy it is to change database to Postgre in Rails. In this heroku tutorial you will see just how easy it is.

To Summarize

I am having a lot of fun with rails. I already built two  small applications in just a few days. you can clearly see the advantages of it.
It's always good to learn new stuff especially in the software development field.
And why be limited to only one technology? Hope this guide helped you out in anyway.

May the force be with you



Friday, October 5, 2012

Cancel button for KnockOut form


I recently built a dynamic form using KnockOut.
This is how that page worked:

A user selectes a person from a list, an AJAX request will post the person id to the server which will then return  a JSON object of that person info (phone, name, age...) I didn't know which info will come back for that person. this is why the form is dynamic. anyway I decided to use a data-bind of template (there were a few a kinds of fields not just text boxes) so template with jQuery templates created a very cool dynamic form.

Now a new demand came saying I should add a cancel button to the form. after a quick Google search I came across this post: guarding your model in a very very good blog for KnockOut knockmeout.net,
anyway accepting changed for a specific observable is nice.. but didn't fit my needs for a full form cancel button. so I decided to go with a simple solution. I will keep my original native JSON object that came back from my AJAX request!

so it will go something like this:


// callback function from server
function AjaxCallback (model) {
   // page is a namespace 
   var tempModel = {};
   // important making a new object (tempModel) so 
   // the copyModel won't be a reference
   $.extend(tempModel, model);
   page.copyModel = tempModel; 
   UpdateModel (model);
function SwitchModel (modelJSON) {
   ko.mapping.fromJS(page.copyOfModel, {}, page.model);
   // we will need to apply the bindings again so the view will update.
   ko.applyBindings(page.model);
}
function CancelChange () {
   UpdatehModel (page.copyModel);
}

function SavePerson () {
   var jsonModel = ko.mapping.toJS(page.model);

   // ------- save the person through ajax

   // don't forget to update the copy model so if 
   // the cancel button will be
   // clicked the last changes won't disappear.. so:
   // better if placed in the success callback of the ajax request
   page.copyModel = jsonModel;
}


page.model is a model i assume you already have on your page. I only gave to parts of the code needed for a cancel button.

And that's pretty much it...very simple but effective way to create a cancel button
for the whole KnockOut form

Saturday, September 22, 2012

jQuery mobile image gallery

I started playing around with jQuery mobile and i think its great!
anyway i needed a simple image gallery for this small app and found the
following tutorial: jQuery mobile gallery which is nice and great to start with.
but the code is not that good... (js code) i didn't like things like:
code duplication, duplicate selectors, being just functions and not an object, and the fact that the selected image and first and last image is being handled by giving classes to elements on your screen. that is really bad in my book.

anyway i did a little re-factoring/changes and thought, why not share?

* note: blogger keeps adding values to the href of anchors with a hash tag. don't forget to remove them, and keep just the hash tag like: #imgshow

so this is what i did
the HTML looks like this:

the gallery itself



the dialog (should be placed outside you page content tag i have put it in the master layout)



just add this two to your view (html page) and you will be fine.

and a simple css (didn't change):

.gallery_content a img { height:80px; width:80px;
    padding:3px;
    background-color:#222;
}
 
#prevbtn, #nextbtn {
    margin:10px 15px;
}

now for the interesting part... our JavaScript!
so lets break it down.

first part, initializing the gallery:

the old code looked like this:

$('.gallerycontent img').bind('tap',function(){
  var src = $(this).attr("src");
  var alt = $(this).attr("alt");
  $('#dialogcontent').empty().append('' );
  $('#dialoghead').empty().append('

' + alt + '

' ); $(this).parent().addClass('selectedimg'); });

The new re-factored init method will look like this:

var self = this;
    var allImages = null;
    var currentImage = null;

    function init() {
        allImages = self.getImages();
        allImages.bind('tap',function(){
            switchImages ($(this));
        });

        self.bindEvents();
    }
    
    this.getImages = function () {
        return $('#galleryContent img');
    }


Now 2 functions to show the next and previous images

function switchImages (imgToSwitch) {
   var src = imgToSwitch.attr("src");
   var alt = imgToSwitch.attr("alt");
        
   currentImage = imgToSwitch;
   // insert the image to the dialog's body 
   $('#dialogcontent').empty().append('' );
   // change the dialog header text
   $('#dialoghead h2').text(alt);
}

this.goNext = function () {
    // check if the current image is the last image if so get the first image
    // else just get the next image
    if (currentImage.is(allImages.last())) {
        var next = allImages.first();
    } else {
        var next = currentImage.parent().next().find("img");
    }
 
    switchImages(next);
}

this.goPrev = function () {
    // check if the current image is the first image if so get the last image
    // else just get the previous image
    if (currentImage.is(allImages.first()))
        var prev = allImages.last();
    else            
        var prev = currentImage.parent().prev().find("img");

    switchImages(prev);
}


the old next and prev functions from that tutorial were complete "copy paste" of the same code in the init function. instead of just extracting that logic to a function.

Finally handling the events for the gallery

old code from tutorial:

$('#nextbtn').bind('tap',function(event, ui){
    gonext();
});
 
$('#imgshow').bind('swipeleft',function(event, ui){
    gonext();
});
 
$('#prevbtn').bind('tap',function(event, ui){
    goprev();
});
 
$('#imgshow').bind('swiperight',function(event, ui){
    goprev();
});



New code: (no need for that empty anonymous functions)

this.bindEvents = function () {
    $('#nextbtn').bind('tap', self.goNext);
    $('#imgshow').bind('swipeleft', self.goNext);
    $('#prevbtn').bind('tap', self.goPrev);
    $('#imgshow').bind('swiperight', self.goPrev);
}


So.. after all the code changes we now have an object not just a bunch of functions , we eliminated the code duplicates and the coupling of logic with UI (the first, last and current image was determined by giving a class to that element) 

This is the complete JS code, just put it in you .js file and you can create an instance of it at document ready event.

var page = {};

$(document).bind("pageinit", function() {
    // creating a new instance of gallery
    page.gallery = new gallery();
});

function gallery () {
    var self = this;
    var allImages = null;
    var currentImage = null;

    function init() {
        // selecting all images just once.
        allImages = self.getImages();
        // add the event for each image in our gallery
        allImages.bind('tap',function(){
            var currImg = $(this);
            switchImages (currImg);
        });

        self.bindEvents();
    }
    
    this.getImages = function () {
        // selector for all gallery images
        return $('#galleryContent img');
    }

    this.bindEvents = function () {
        // events for our gallery buttons 
        $('#nextbtn').bind('tap', self.goNext);
        $('#imgshow').bind('swipeleft', self.goNext);
        $('#prevbtn').bind('tap', self.goPrev);
        $('#imgshow').bind('swiperight', self.goPrev);
    }
    
    function switchImages (imgToSwitch) {
        // just switching the old image the new one
        var src = imgToSwitch.attr("src");
        var alt = imgToSwitch.attr("alt");
        
        currentImage = imgToSwitch;
        $('#dialogcontent').empty().append('' );
        $('#dialoghead h2').text(alt);
    }

    this.goNext = function () {
        // check if the current image is the last image if so get the first image
        // else just get the next image
        if (currentImage.is(allImages.last())) {
            var next = allImages.first();
        } else {
            var next = currentImage.parent().next().find("img");
        }
 
        switchImages(next);
    }

    this.goPrev = function () {
        // check if the current image is the first image if so get the last image
        // else just get the previous image
        if (currentImage.is(allImages.first()))
            var prev = allImages.last();
        else            
            var prev = currentImage.parent().prev().find("img");

        switchImages(prev);
    }    

    init();
}

this final JS code along with the short HTML and css will give you a pretty descent gallery for your jQuery mobile app.


enjoy!



Friday, December 2, 2011

Fun installations with NuGet, Extension Manager and Web Platform

so... i have read in blogs mentions and stuff about NuGet (formerly known as NuPack)
but i never actually used it..

i started using it last week at work and i love it! its easy to use, you have so much packages there but also you have the rating and the amount of downloads which is very important..
you want to know if the "package" you are about to start using has enough people using it so you can get support online. also it tells you about updates for those packages.

so what are you waiting for? go to tools --> Extension Manager
and install NuGet Package Manager
you wont regret it.

speaking of the Extension Manager.. same thing! use to the Extension Manager to power up your Visual Studio, i installed these extensions:

Nuget Package Manager - of course
Productivity Power Tools - a must have. by Microsoft itself, all kinds of small improvements for visual studio. read about Power Tools


Visual Nunit 2010 - just because its more convenient then the regular desktop ui for Nunit (and of course installed Nunit through NuGet)

JSEnhancements - very nice and convenient extension for JavaScript, it lets you collapse code blocks in JavaScript , i really think it saves me a lot of time when editing large JS files.
you can install it here

there is the JavaScript Parser extension which is very popular. i didn't get a chance to download it yet but its suppose to be good.

the next thing i played with this week was the Web Platform Installer in iis7

same idea like the extension manager but can save you more valuable time..
ill explain.. this week i decided to check out some CMS systems and see which is the best for me. for each CMS i had to go to there websites download, read how to install it and waste a lot of my time. but then i real about the Web Platform Installer, just got in clicked on the CMS category and with a click of a button install any CMS i want and start playing with it.

final thoughts:
since when Microsoft started being so cool? ;-) and why didn't i start using and playing with this stuff before?

have a good one, ill get back to coding

Wednesday, June 15, 2011

Making a site social

making a site social

i recently decided to find a new job. after A couple of interviews i got accepted to a cool little company: http://www.gigya.com

one of the company's services is a JavaScript api to help you, in a very easy way, connect your site to all social networks
because everyone knows that today its all about social networks...
so i decided to give the product a try and experiment with it before i even started working there.

making a site social has a lot of benefits like increasing traffic, creating  a better surfing experience for the user by connecting with an account he already has on Facebook
and seeing his picture on your site. and so on...

so here is the full coverage of making a site social using Gigya's api.

* Gigya's service is free of charge as long as you have less than a THOUSAND unique users each month. 

the first step we need to take in order to start working with the api is to register on the site:
https://www.gigya.com/site/Register.aspx



after registration we will receive an api key.
which is enough to play around with the api and check it out.
but... if you want to upload it to production and use it properly you will have to set api keys you get from each social network.


press the edit link, then press the site settings button on the right. this will lead you to the settings page. there are a lot of settings and permissions stuff you can set there.
but first of all get the information needed for each social network you plan on working with.


now we can get to work,

i think the first basic thing a site needs is the ability to give the user the power to share things with their friends
so...  if we take a look at the available plugins page http://www.gigya.com/site/partners/widgets.aspx
there will be 2 plugins that fits us a "share" plugin and a "Share Bar" plugin

the share bar plugin is more what i had in mind for my site so ill just start with it..



people are very used to these kinds of social bars on websites which is good for us.

so each plugin in the plugin page has a wizard to help you customize the plugin the way you want with different appearances and to select the social networks.

then the wizard of course produces the code you need to put in your site in order for that plugin to work.
the first piece of code you will need to add to your site in order to work with the api is the api itself :) and the api key.
code produced by the wizard looks like this:

<script type="text/javascript" src="http://cdn.gigya.com/js/socialize.js?apiKey=xxxxxxxxxxxxx"></script>

<script type="text/javascript">

    
var conf= { 

      APIKey: 'xxxxxxx-xxxxxxxxxxxxxx'

    }

</script>



this script is supposed to be added in the head. for the first line its true :)
but of course putting scripts in our page is not good layer separation lines 3 to 5 should go in some general js file in your site.
also so we wont just declare a global variable in the global namespace i enter the api key to the Gigya api namespace like so:

gigya.services.socialize.apiKey =
{
          APIKey: 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
         , enabledProviders: 'facebook,twitter'
}

the next piece of code we get is something like this:
depending of course on what settings and social networks you choose in the wizard.
i only needed this 4.

<script type="text/javascript">
var act = new gigya.services.socialize.UserAction();
act.setUserMessage("This is the user message");
act.setTitle("This is my title");
act.setLinkBack("http://www.gigya.com");
act.setDescription("This is my Description");
act.addActionLink("Read More", "http://www.gigya.com");
var showShareBarUI_params=
{
  containerID: 'componentDiv',
  shareButtons: 'facebook-like,google-plusone,share,twitter',
  userAction: act
}
</script>
<div id="componentDiv"></div>
<script type="text/javascript">

gigya.services.socialize.showShareBarUI(conf,showShareBarUI_params);
</script>

here, don't forget to change the domain Gigya to your domain.
this code will render the share bar, inside the: <div id="componentDiv"></div>
again, as before, we don't want these scripts to be inside our HTML. so we will extract the JavaScript code to a function (with a good name like RenderShareBar or similar...)
inside a js file, and call it from the onload or the $(document).ready, whatever, as long as we keep our layers separated.

and that's it! you will have a share bar in your site with just minutes of work, very cool.

so in conclusion:

making your site social is always good. so you definitely want to do it, and you can do it by yourself of course all social networks like Facebook and twitter has there
own api you can use to add and use them in your site, and its not that hard. but.... if you want to add multiple social networks then it starts getting annoying...
the Gigya api wraps all of this networks in one easy to use package with is very convenient.
another benefit is that you wont have to worry if a certain api of one of the networks changes.
another cool thing is the analytics you get in the dashboard. where you can monitor the "social activity" on your site.

http://www.gigya.com/public/platform/analyze.aspx

so that's it with the registration and share bar.
next post ill try the social login feature which i think is the most important one. so annoying when sites make you register and don't have some kind of social login...  :)

May the force be with you.




Monday, May 16, 2011

Using a css reset

After seeing that a lot of people at work don’t use a css reset I want to address the subject.

I highly recommend using a css reset purely for the reason that it makes your life a little bit easier, when developing a cross browser site.

While developing apage and building it div by div paragraph after paragraph we start to see little differences between all of our browsers.
The reason for that is that different browsers give different default styles to html elements.
That’s very annoying for us.
So the first thing I recommend doing is putting a css reset on your site while starting to develop. it can save you a lot of time and css attributes
because in the end while developing you in fact do override the browser's default style settings for element. But.. it takes you more time to find those places (thank god for firebug)
and… You are writing all kind of attributes like: margin:0px; padding:0px; in a lot of your classes.

So that’s exactly what a css reset does, it overrides those default style settings and then you can start off fresh.

There are css reseters out there but I think the two most common are:
YUI css reset,
and a css reset by erik meyer.
I use erik's css reset for quite some time and its great.

You can download them here:

YUI css reset

Erik meyers

For already developed sites:
I wouldn't recommend to just add a css reset file to your site unless you are willing to spend the time required to go over all of your site with all the browsers and check to see that the css reset didn’t destroy anything…

In conclusion:
Don’t get me wrong this is not some kind of magic trick for building cross browser websites
you will still have annoying problems of course. But surely there will be less. And at least it saves us some time.