Web Side Down

dynamic web development

Backbone Forms: How to Get Ids for Objects Created on the Client Side?

I am building an application which is built with Backbone.js. It contains several forms, which make it possible to create sub-items in collections. I run into the issue of getting the id for the recently created items. Let me explain the scenario:

  1. a new model instance is created with and an empty id
  2. the form gets saved triggering a POST or PUT request
  3. the server receives and saves the new and updated items
  4. the new items get the ids filled out
  5. all items are sent back with updated server-side ids

The issue is with mapping the new ids to the instances which are on the client side without an id.

Backbone.js generates a unique client-side cid for every object. The idea was to serialize the cid and send it back from the server with the server side id. As server I use rails. I added new virtual attribute cid to the model and serialized it. For the client models serializing (toJSON) and parsing needed to be updated. Method toJSON was the easy part:

tojson.js
1
2
3
4
toJSON: function() {
  return _.extend(toJSON.__super__.constructor.apply(this, arguments),
      { cid: this.cid })
}

Bit trickier is handling of the response coming from the server. It’s necessary to identify the existing item using the cid and update it with the new server side id. After exploring several possible ways, how to do it wrong, I was advised to override the parse method.

parse.js
1
2
3
4
5
6
7
8
parse: function (resp) {
  return _.map(resp, function (attrs) {
    var cid = attrs.cid;
    delete attrs.cid;
    var existing = this.get(cid);
    return existing ? existing.set(attrs).attributes : attrs;
  }, this);
}

That simple definition of the parse method showed me the elegance of backbone. Searching for a simple solution proved to be worthwhile.

Restricting Models With Heimdallr

"deck of cards, some have visible faces"

I found myself several times implementing the logic for restictions in controllers. Althought that might be fine, when the things get more complex, this practice can become hard to maintain. As modeling restrictions belongs to the core logic of the application, perhaphs they should be placed there..

That’s what heimdallr is supposed to resolve. This gem provides model level security by wrapping the model classes and instances by a proxy. The access rights are declared in the model:

card.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Card < ActiveRecord::Base
  include Heimdallr::Model

  belongs_to :person

  attr_accessible :suit, :rank, :backside

  restrict do |person, card|

    if person.arbiter?
      # the arbiter can do anything
      scope :fetch, -> {}
    elsif person.playing?
      # if the user is playing, only the card at hand is visible
      scope :fetch, -> do
        where(['person_id = ?', person])
      end
    end
  end
end

The restrict block can take more parameters, based on these we can decide how to restrict the model. The last parameter (card in the example) is an instance of the model, if it is nil the model class was passed to the restrict block. The restriction can be thus called on either the model class or on a concrete instance: Card.restrict(person) vs card.restrict(person).

Heimdallr maintains a scope for fetching and deletion. Scope restriction are obviously useful when restricting the model class. Calling all on the proxied model returns only the cards visible by the person. Wondering how to simply ask whether a card instance is visible by the person? card.restrict(person).visible? does just that. For testing destroyability of a record there is destroyable?.

I covered briefly scope restriction using heimdallr in this post. However, there is yet more how heimdallr can help. Finer restrictions, such as attribute visibility and updatability are often crucial as well. But let’s leave this for later.

Non-Modal Inline Dialogs: Ask Questions in Awesome Ways

"simple modal dialog with a yes-no question"

Asking questions, confirmations from the users is a pretty usual part of any user interface. Still often I find tackling this simple task solved in unsatisfying way. The simplest solution is the confirm('ask your question..'); dialog. However, this often ruins the otherwise possibly clean design. Confirm dialogs are modal and therefore users can not proceed further actions without answering the questions. But what if you do not need immediate answers? Often it is enough leaving the dialog questions opened. In such situation try using “inline dialogs”.

Let’s build a simple scenario. We have three simple events which the user can trigger: calling a firemen, calling police or ambulance. Obviously triggering these events could be useful to handle with a simple question before they are really triggered. If this security question is answered positively, the event is triggered, otherwise the original Call the … link is rendered. The dialog blocks are divided into a trigger and question part.

inline-dialogs.html
1
2
3
4
5
6
7
8
9
<DIV CLASS='dialog_block' DATA-MESSAGE='Calling the firemen!'>
  <A HREF="#" CLASS="dialog_trigger">Call the Firemen!</A>
  <DIV CLASS="dialog_question">
    Call?
    <A HREF="#" CLASS="answer_yes">Yes</A>
    <A HREF="#" CLASS="answer_no">No</A>
  </DIV>
</DIV>
<!-- do something similar for the two other calls -->

For handling the dialog actions I use jQuery now. We need only three simple callbacks for handlers: activation of the question trigger, handler for the yes and the no answer.

inline-dialogs.js
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
var turnOffDialogQuestion = function(el) {
  $dialog_block = getDialogBlock(el);
  $dialog_block.find('.dialog_question').fadeOut('fast',
    function() { $dialog_block.find('.dialog_trigger').fadeIn('fast'); });
};
var getDialogBlock = function(el) {
  return $(el).parents('.dialog_block');
};
$(document).ready(function() {
  $('.dialog_trigger').click(function(ev) {
    $dialog_block = getDialogBlock(this);
    $(this).fadeOut('fast',
      function() { $dialog_block.find('.dialog_question').fadeIn('fast'); });
    ev.preventDefault();
    return false;
  });
  $('.dialog_question .answer_yes').click(function(ev) {
    alert(getDialogBlock(this).data('message'));
    turnOffDialogQuestion(this);
    ev.preventDefault();
    return false;
  });
  $('.dialog_question .answer_no').click(function(ev) {
    turnOffDialogQuestion(this);
    ev.preventDefault();
    return false;
  });
});

The full source codes of this simple example can be downloaded from here: HTML, javascript. By following on the HTML link the example can be also tried out.

Lorem Ipsum

"first words"

Welcome to a yet another blog about web development. Why should you bother reading posts from this one? I see web development as a platform to understand different technologies, languages or concepts. Web is still a dominating media, understanding it has practical reasons, it can give you a way to make living. However, I find it more practical to look at practical things playfully (..isn’t playfulness the best way how to understand things anyway..?). There is going to be only one sticking point in the posts, and that’s the Web. I will not stick to languages, technologies,.. I’m not restricting myself to pure programming topics, we can sail to post about web design topics just as well.

I hope, you’ll find this useful and a bit refreshing.. So worth of following. This blog has an rss-feed and a newsletter, please subscribe if you want to be updated regularly.