Jquery-ujs and Jquery Trigger

ajax using jquery

jQuery’s ajax method’s success callback function takes three parameters. Here is the api .

1
success(data, textStatus, jqXHR)

So if you are making ajax call using jQuery the code might look like

1
2
3
4
5
6
$.ajax({
  url: 'ajax/test.html',
  success: function(data, textStatus, jqXHR) {
    console.log(data);
  }
});

ajax using jquery-ujs

If you are using Rails and jquery-ujs then you might have code like this

1
2
3
4
5
<a href="/users/1" data-remote="true" data-type="json">Show</a>

$('a').bind('ajax:success', function(data, status, xhr) {
  alert(data.name);
});

Above code will not work. In order to make it work the very first element passed to the callback must be an event object. Here is the code that will work.

1
2
3
$('a').bind('ajax:success', function(event, data, status, xhr) {
  alert(data.name);
});

Remember that jQuery api says that the first parameter should be “data” then why we need to pass event object to make it work.

Why event object is needed

Here is snippet from jquery-ujs code

1
2
3
success: function(data, status, xhr) {
  element.trigger('ajax:success', [data, status, xhr]);
}

The thing about trigger method is that the event object is always passed as the first parameter to the event handler. This is why when you are using jquery-ujs you have to have the first parameter in the callback function an event object.

XSS and Rails

XSS stands for Cross-site scripting. However it has nothing to do with cross-site. It has everything to do with your site.

XSS is consistently a top web application security risk as per The Open Web Application Security Project (OWASP) .

XSS vulnerability allows hacker to execute JavaScript code.

Your site has a form. I enter <script>alert(document.cookie)</script> and I hit submit. If I see an alert then it means I can execute JavaScript code on your site and your site has XSS vulnerability.

If a hacker can execute JavaScript code then the hacker can see your cookie.

If you are logged into your application then your application sets a cookie. That is how your application knows that you are logged in.

If a hacker can see your cookie then the hacker can log in.

By the way having SSL does not protect the site from XSS vulnerability.

Prevention

An easy way to prevent XSS is to not to allow users to execute JavaScript code. This is the reason why when you go to post comment many sites have messages similar to this one.

limited html example

Some sites allow some html code and other do not allow any html code at all.

It is possible for the hacker to insert JavaScript code in your system. For example if database stores <script>alert(document.cookie)</script> then JavaScript code has come inside the application. However as long as you deny the opportunity for that code to be executed in browser you are safe.

You can also take precaution and sanitize all user input so that JavaScript code does not comes into the system at all.

The right approach depends on your need and the application framework you are working with.

A practical example

It is very commont to display address in a formatted way. Usually the code is something like this

1
2
address_array = [name, address1, address2, city_state_zip, country_name].compact
address_array.join('<br />')

Since here the address is being separated by an html tag <br />. When developer looks at the html page he/she sees the <br /> tag literally on the screen so the developer comes back to code and marks the string as html_safe.

1
2
address_array = [name, address1, address2, city_state_zip, country_name].compact
address_array.join('<br />').html_safe

Now the browser renders the address with proper <br /> tag and the address looks nicely formatted. The developer moves on.

However notice that developer has marked user input data like address1 as html_safe and as I discussed earlier this is exposing your site to XSS attack.

Here is how it should be fixed without exposing any security issue.

1
2
address_array = [name, address1, address2, city_state_zip, country_name].compact
address_array.map{ |i| html_escape(i) }.join('<br />').html_safe

Notice that user input elements are being subjected to html_escape before they are marked as html_safe.

What tools Rails provides

In the earlier version of Rails we were encouraged to use <%= h post.comment %> in views. Here h is a short name for html_escape. In Rails 3.x the content is automatically escaped. It means if the hacker enters <script>alert(document.cookie)</script> then after html_escape has performed its operation the browser sees "&lt;script&gt;alert(document.cookie)&lt;/script&gt;". In this way the user does not get to see the alert message which is a good thing. It means users cannot execute JavaScript code on your site and your site is XSS safe.

If you do want to format the text a little bit then you can use simple_format . If user enters a bunch of text in text area then simple_format can help make the text look pretty without compromising security. It will strip away <script> and security sensitive tags. html_escape internally uses sanitize method. Checkout that method to see what options you can pass. Think before you act because you might be opening a security vulnerability.

Also be careful with raw method. It will output without escaping the string.

In case of Json you need to handle escaping yourself

Note that when user entered <script>alert(document.cookie)</script> in the textarea then database stored the value as <script>alert(document.cookie)</script> . No escaping is done before storing the value in the database. It is the ERB that does the escaping and ensures that site is protected.

All is well and after a few months boss comes and asks to make that page ajaxy. Now data is sent to browser in JSON format.

Now Controller looks like format.json { render json: @user }.

This will produce JSON structure like this "{\"about\":\"<script>alert(document.cookie)</script>\"}".

On the client side you have code to display the content. $('body').append(data.about). Well when the about content is added to dom the script will be executed and now your site is vulnerable to XSS.

You would think that using json_escape should solve the problem. However json_escape produces invalid JSON. Yes that is right. The output of json_escape is invalid JSON. There is an open pull request to take care of that issue.

The point is that if you are passing JSON data to be displayed on the browser then , by default, you do not have the escape protection that ERB provides.

CSRF and Rails

CSRF stands for Cross-site request forgery.

Unlike XSS CSRF does not try to steal your informationt to log into the system. CSRF assumes that you are aleady logged in at your site and when you visit comments section of some other site then an attack is done on your site without you knowing it.

Here is how it might work

  • User logs in at www.mysite.com .
  • User visits www.gardening.com site since he is interested in gardeing .
  • He is browsing the comments posted on the gardening.com forum and one of the comments posted is <img src="http://www.mysite.com/grant_access?user_id=1&project_id=123" />
  • If the user is admin of the project “123” then unknowingly he might grant access to user_id 1 .

I know. You are thiniking that loading an image will make a GET request and granting access is hidden behind POST request. So you are safe. Well the hacker can easily change code to make a POST request. The code might look like this

1
2
3
4
<script>
 document.write('<form name=hack method=post action="http://mysite.com/grant_access?user_id=1&project_id=123"></form>')
</script>
<img src='' onLoad="document.hack.submit()" />

Now when the image is loaded then a POST request is sent to the server and the application might grant access to this new user. Not good.

Prevention

In order to prevent such things from happening Rails uses authenticity_token.

If you look at source code of any form generated through Rails scaffolding you will see that form markup contains following code

<input name="authenticity_token" type="hidden" value="LhT7dqqRByvOhJJ56BsPb7jJ2p24hxNu6ZuJA+8l+YA=" />.

The exact value of the authenticity_token will be different. When form is submitted then Rails checks the authenticity_token and only when it is verified the request is sent for further processing.

In a brand new rails application the application_controller.rb has only one line.

1
2
3
class ApplicationController < ActionController::Base
  protect_from_forgery
end

That line protect_from_forgery checks for the authentication of the incoming request.

Here is code that is responsible for generating csrf_token.

1
2
3
4
# Sets the token value for the current session.
def form_authenticity_token
  session[:_csrf_token] ||= SecureRandom.base64(32)
end

Since this “csrf_token” is a random value there is no way for hacker to know what the “csrf_token” is for my session. And he will not be able to pass the correct “authenticity_token”.

Note that if the site is vulnerable to XSS then the hacker submits request as if he is logged in and in that case the CSRF attack will go through.

Tsort in Ruby and Rails Initializers

You have been assigned the task of figuring out in what order following tasks should be executed given their dependencies on other tasks.

1
2
3
4
5
Task11 takes input from task5 and task7.
Task10 takes input from task11 and task3.
Task9 takes input from task8 and task11.
Task8 takes input from task3 and task7.
Task2 takes input from task11.

If you look at these tasks and draw a graph then it might look like this.

directed acyclic graph

Directed acyclic graph

The graph shown above is a “Directed acyclic graph” . In Directed acyclic graphs if you start following the arrow then you should never be able to get to the node from where you started.

Directed acyclic graphs are great at describing problems where a task is dependent on another set of tasks.

We started off with a set of tasks that are dependent on another set of tasks. To get the solution we need to sort the tasks in such a way that first task is not dependent on any task and the next task is only dependent on task previously done. So basically we need to sort the directed acyclic graph such that the prerequisites are done before getting to the next task.

Sorting of directed acyclic graph in the manner described above is called topological sorting .

TSort

Ruby provides TSort which allows us to implement “topological sorting”. Here is source code or tsort .

Lets write code to find solution to the original problem.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
require "tsort"

class Project
  include TSort

  def initialize
    @requirements = Hash.new{|h,k| h[k] = []}
  end

  def add_requirement(name, *requirement_dependencies)
    @requirements[name] = requirement_dependencies
  end

  def tsort_each_node(&block)
    @requirements.each_key(&block)
  end

  def tsort_each_child(name, &block)
    @requirements[name].each(&block) if @requirements.has_key?(name)
  end

end

p = Project.new
p.add_requirement(:r11, :r5, :r2)
p.add_requirement(:r10, :r11, :r3)
p.add_requirement(:r9, :r8, :r11)
p.add_requirement(:r8, :r3, :r7)

puts p.tsort

If I execute above code in ruby 1.9.2 I get following result.

1
2
3
4
5
6
7
8
r5
r2
r11
r3
r10
r7
r8
r9

So that is the order in which tasks should be executed .

How Tsort works

tsort requires that following two methods must be implemented.

#tsort_each_node - as the name suggests it is used to iterate over all the nodes in the graph. In the above example all the requrirements are stored as a hash key . So to iterate over all the nodes we need to go through all the hash keys. And that can be done using #each_key method of hash.

#tsort_each_child - this method is used to iterate over all the child nodes for the given node. Since this is directed acyclic graph all the child nodes are the dependencies. We stored all the dependencies of a project as an array. So to get the list of all the dependencies for a node all we need to do is @requirements[name].each.

Another example

To make things clearer lets try to solve the same problem in a different way.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
require "tsort"

class Project
  attr_accessor :dependents, :name
  def initialize(name)
    @name = name
    @dependents = []
  end
end

class Sorter
  include TSort

  def initialize(col)
    @col = col
  end

  def tsort_each_node(&block)
    @col.each(&block)
  end

  def tsort_each_child(project, &block)
    @col.select { |i| i.name == project.name }.first.dependents.each(&block)
  end
end

r5 = Project.new :r5
r2 = Project.new :r2

r11 = Project.new :r11
r11.dependents << r5
r11.dependents << r2

r3 = Project.new :r3
r10 = Project.new :r10
r10.dependents << r11
r10.dependents << r3

r8 = Project.new :r8
r9 = Project.new :r9
r9.dependents << r8
r9.dependents << r11

r7 = Project.new :r7
r8.dependents << r3
r8.dependents << r7

col = [r5, r2, r11, r3, r10, r9, r7, r8, r5]

result = Sorter.new(col).tsort
puts result.map(&:name).inspect

When I execute the above code this is the result I get

1
[:r5, :r2, :r11, :r3, :r10, :r7, :r8, :r9]

If you look at the code here I am doing exactly the same thing as in the first case.

Using before and after option

Let’s try to solve the same problem one last time using before and after option. Here is the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
require "tsort"

class Project
  attr_accessor :before, :after, :name
  def initialize(name, options = {})
    @name = name
    @before, @after = options[:before], options[:after]
  end
end

class Sorter
  include TSort

  def initialize(col)
    @col = col
  end

  def tsort_each_node(&block)
    @col.each(&block)
  end

  def tsort_each_child(project, &block)
    @col.select { |i| i.before == project.name || i.name == project.after }.each(&block)
  end
end

r11 = Project.new :r11
r7 = Project.new :r7
r9 = Project.new :r9
r5 = Project.new :r5
r2 = Project.new :r2, after: :r5, before: :r11
r3 = Project.new :r3, after: :r11
r8 = Project.new :r8, after: :r7, before: :r9
r10 = Project.new :r10, before: :r7

col = [r5, r2, r11, r3, r10, r9, r7, r8, r5]

result = Sorter.new(col).tsort
puts result.map(&:name).inspect

Here is the result.

1
[:r5, :r2, :r11, :r3, :r10, :r7, :r8, :r9]

Sorting of rails initializer

If you have written a rails plugin then you can use code like this

1
2
3
initializer 'my_plugin_initializer',after: 'to_prepare', before: 'before_eager_load' do |app|
 ....
end

The way rails figures out the exact order in which initializer should be executed is exactly same as I illustrated above. Here is the code from rails.

1
2
3
4
5
6
7
8
9
alias :tsort_each_node :each
def tsort_each_child(initializer, &block)
  select { |i| i.before == initializer.name || i.name == initializer.after }.each(&block)
end
............
............
initializers.tsort.each do |initializer|
  initializer.run(*args) if initializer.belongs_to?(group)
end

When Rails boots it invokes a lot of initializers. Rails uses tsort to get the order in which initializers should be invoked. Here is the list of unsorted initializers. After sorting the initializers list is this .

Where else it is used

Bundler uses tsort to find the order in which gems should be installed.

Tsort can also be used to statically analyze programming code by looking at method dependency graph.

Image source: http://en.wikipedia.org/wiki/Directed_acyclic_graph

Alias vs Alias_method

It comes up very often. Should I use alias or alias_method . Lets take a look at them in a bit detail.

Usage of alias

1
2
3
4
5
6
7
8
9
10
class User

  def full_name
    puts "Johnnie Walker"
  end

  alias name full_name
end

User.new.name #=>Johnnie Walker

Usage of alias_method

1
2
3
4
5
6
7
8
9
10
class User

  def full_name
    puts "Johnnie Walker"
  end

  alias_method :name, :full_name
end

User.new.name #=>Johnnie Walker

First difference you will notice is that in case of alias_method we need to use a comma between the “new method name” and “old method name”.

alias_method takes both symbols and strings as input. Following code would also work.

1
alias_method 'name', 'full_name'

That was easy. Now lets take a look at how scoping impacts usage of alias and alias_method .

Scoping with alias

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class User

  def full_name
    puts "Johnnie Walker"
  end

  def self.add_rename
    alias_method :name, :full_name
  end
end

class Developer < User
  def full_name
    puts "Geeky geek"
  end
  add_rename
end

Developer.new.name #=> 'Gekky geek'

In the above case method “name” picks the method “full_name” defined in “Developer” class. Now lets try with alias.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class User

  def full_name
    puts "Johnnie Walker"
  end

  def self.add_rename
    alias :name :full_name
  end
end

class Developer < User
  def full_name
    puts "Geeky geek"
  end
  add_rename
end

Developer.new.name #=> 'Johnnie Walker'

With the usage of alias the method “name” is not able to pick the method “full_name” defined in Developer.

This is because alias is a keyword and it is lexically scoped. It means it treats self as the value of self at the time the source code was read . In contrast alias_method treats self as the value determined at the run time.

Overall my recommendation would be to use alias_method. Since alias_method is a method defined in class Module it can be overridden later and it offers more flexibility.

Jquery Deferred

Topics covered

  • Usage of Deferred in Ajax call
  • Non ajax usage of Deferred
  • Resolve and fail method
  • Practical usage of Deferred with caching example

Click here to download jsfiddle.net links for practice.

Jquery Delegate

Topics covered

  • Delegates solves live problems
  • Delegate preferred over live

Click here to download jsfiddle.net links for practice.

Understanding Bind and bindAll in Backbone.js

Backbone.js users use bind and bindAll methods provide by underscore.js a lot. In this blog I am going to discuss why these methods are needed and how it all works.

It all starts with apply

Function bindAll internally uses bind . And bind internally uses apply. So it is important to understand what apply does.

1
2
3
4
var func = function beautiful(){
  alert(this + ' is beautiful');
};
func();

If I execute above code then I get [object window] is beautiful. I am getting that message because when function is invoked then this is window, the default global object.

In order to change the value of this we can make use of method apply as given below.

1
2
3
4
var func = function beautiful(){
  alert(this + ' is beautiful');
};
func.apply('Internet');

In the above case the alert message will be Internet is beautiful . Similarly following code will produce Beach is beautiful .

1
2
3
4
var func = function beautiful(){
  alert(this + ' is beautiful');
};
func.apply('Beach'); //Beach is beautiful

In short, apply lets us control the value of this when the function is invoked.

Why bind is needed

In order to understand why bind method is needed first let’s look at following example.

1
2
3
4
5
6
7
8
function Developer(skill) {
  this.skill = skill;
  this.says = function(){
    alert(this.skill + ' rocks!');
  }
}
var john = new Developer('Ruby');
john.says(); //Ruby rocks!

Above example is pretty straight forward. john is an instance of Developer and when says function is invoked then we get the right alert message.

Notice that when we invoked says we invoked like this john.says(). If we just want to get hold of the function that is returned by says then we need to do john.says. So the above code could be broken down to following code.

1
2
3
4
5
6
7
8
9
function Developer(skill) {
  this.skill = skill;
  this.says = function(){
    alert(this.skill + ' rocks!');
  }
}
var john = new Developer('Ruby');
var func = john.says;
func();// undefined rocks!

Above code is similar to the code above it. All we have done is to store the function in a variable called func. If we invoke this function then we should get the alert message we expected. However if we run this code then the alert message will be undefined rocks!.

We are getting undefined rocks! because in this case func is being invoked in the global context. this is pointing to global object called window when the function is executed. And window does not have any attribute called skill . Hence the output of this.skill is undefined.

Earlier we saw that using apply we can fix the problem arising out of this. So lets try to use apply to fix it.

1
2
3
4
5
6
7
8
9
function Developer(skill) {
  this.skill = skill;
  this.says = function(){
    alert(this.skill + ' rocks!');
  }
}
var john = new Developer('Ruby');
var func = john.says;
func.apply(john);

Above code fixes our problem. This time the alert message we got was Ruby rocks!. However there is an issue and it is a big one.

In JavaScript world functions are first class citizens. The reason why we create function is so that we can easily pass it around. In the above case we created a function called func. However along with the function func now we need to keep passing john around. That is not a good thing. Secondly the responsibility of rightly invoking this function has been shifted from the function creator to the function consumer. That’s not a good API.

We should try to create functions which can easily be called by the consumers of the function. This is where bind comes in

How bind solves the problem

First lets see how using bind solves the problem.

1
2
3
4
5
6
7
8
9
function Developer(skill) {
  this.skill = skill;
  this.says = function(){
    alert(this.skill + ' rocks!');
  }
}
var john = new Developer('Ruby');
var func = _.bind(john.says, john);
func();// Ruby rocks!

To solve the problem regarding this issue we need a function that is already mapped to john so that we do not need to keep carrying john around. That’s precisly what bind does. It returns a new function and this new function has this bound to the value that we provide.

Here is a snippet of code from bind method

1
2
3
return function() {
  return func.apply(obj, args.concat(slice.call(arguments)));
};

As you can see bind internally uses apply to set this to the second parameter we passed while invoking bind.

Notice that bind does not change existing function. It returns a new function and that new function should be used.

How bindAll solves the problem

Instead of bind we can also use bindAll . Here is solution with bindAll.

1
2
3
4
5
6
7
8
9
10
function Developer(skill) {
  this.skill = skill;
  this.says = function(){
    alert(this.skill + ' rocks!');
  }
}
var john = new Developer('Ruby');
_.bindAll(john, 'says');
var func = john.says;
func(); //Ruby rocks!

Above code is similar to bind solution but there are some big differences.

The first big difference is that we do not have to worry about the returned value of bindAll . In case of bind we must use the returned function. In bindAll we do not have to worry about the returned value but it comes with a price. bindAll actually mutates the function. What does that mean.

See john object has an attribute called says which returns a function . bindAll goes and changes the attribute says so that when it returns a function, that function is already bound to john.

Herer is a snippet of code from bindAll method.

1
function(f) { obj[f] = _.bind(obj[f], obj); }

Notice that bindAll internally calls bind and it overrides the existing attribute with the function returned by bind.

The other difference between bind and bindAll is that in bind first paramter is a function john.says and the second parameter is the value of this john. In bindAll first paramter is value of this john and the second parameter is not a function but the attribute name.

Things to watch out for

While developing a Backbone.js application someone had code like this

1
2
3
4
5
6
window.ProductView = Backbone.View.extrend({
  initialize: function() {
    _.bind(this.render, this);
    this.model.bind('change', this.render);
  }
});

Above code will not work because the returned value of bind is not being used. The correct usage will be

1
2
3
4
5
window.ProductView = Backbone.View.extrend({
  initialize: function() {
    this.model.bind('change', _.bind(this.render, this));
  }
});

Or you can use bindAll as given below.

1
2
3
4
5
6
window.ProductView = Backbone.View.extrend({
  initialize: function() {
    _.bindAll(this, this.render);
    this.model.bind('change', this.render);
  }
});

Jquery Live

Topics covered

  • Why use live
  • How it works
  • Things to watch out for

Click here to download jsfiddle.net links for practice.

Enhancing Forms With jQuery

Topics covered

  • Change the color of asterik
  • Replace asterik with text
  • Toggle student id field

Click here to download jsfiddle.net links for practice.