Rails Form Objects

When I started learning Rails, one the first rules of thumb I’ve stumbled upon was “fat model, skinny controller” rule. Being enthusiastic for new things as I am, I immediately took it for face value. Which obviously led to bloated models and spaghetti callbacks.

Time passed and I was happy with the things they were until I’ve seen Gary Bernhardt talking about Service Objects in his Destroy All Software screencast. At the same time I’ve heard Ruby Rogues podcast where the crew of the podcast was talking about Form Objects (I think it was episode 104).

I’ve bit the bullet and tried both and here are my thoughts on them. I’ll start off with Service Objects: the technique is based on capturing services (or I prefer to call them processes — chains of events logically coupled together) in a plain ruby object. I won’t talk about advantages of using Service Object Pattern and will cut down to the point: the bad thing about it is that it encapsulates only single process. If you want to capture another process you have to create a new Object. In case you have multiple controllers with each controller having few different actions you will end up with huge amount of Service Objects all doing roughly the same thing.

Form Objects to the Rescue

Form Object is very similar to the Service Object; the only difference is the philosophy beneath it. Form Object mimics the HTML form being submitted to the server. It is yet another layer placed between your view and controller taking some responsibilities from both (and from model as well). Here is the list of responsibilities I give to Form Objects in my projects:

  1. validation of data,
  2. notifications (both via e-mail and in application),
  3. audit logging (it gives me bad dreams since there is no clean way to do it via models),
  4. handling all the CUD (as in CRUD) actions on the object,
  5. creating nested records (for which you would probably use nested attributes).

As you may have guessed, I mimic almost every model in my project with a Form Object. This way I can keep both my controllers and models free of repetitive logic that simply doesn’t belong there.

Less Words, More Code

There are many ways to implement the Form Object pattern. Here is the way I do it.

First of all lets start with creating the Form Object:

# lib/form_object.rb
class FormObject
include ActiveModel::Model
  def initialize(args={})
args.each do |k,v|
instance_variable_set(“@#{k}”, v) unless v.nil?
end
end
end

In the project I am currently working on I’ve few more methods in the object and few concerns included; I’ve even defined CUD (as in CRUD) methods in the main Form Object (since they are reused in every other form).

Now we can move on to creating a Form Object which will inherit from the Form Object:

# app/forms/todo_form.rb
class TodoForm < FormObject
attr_accessor :todo, :comment
  validates :todo, presence: true
  def self.create_new_todo
if valid?
# Put all logic related to creation of new Todo
# in here — log actions, dispatch e-mails etc
create_todo
end
end
  private
def create_todo
# You can even encapsulate the acutual creation of
# the object into it's separate private method; if
# it's needed of course
Todo.new(...)
end
end

Another thing that we need to do before we are finished — to change controller a little bit:

# app/controllers/todo_controller.rb
class TodoController < ApplicationController
def create
TodoForm.create_new_todo(todo_params)
end
  private
def todo_params
params.require(:todo).permit(:todo, :comment)
end
end

Now there is last small concern left and that is usage of Form Object in your views; I have created a small helper which renders form for Form Object. With just a little patience and Rails API you will build your own in no time.

Final thoughts

In my current project I’ve ended up using both techniques mentioned earlier — for one-time actions such as user registration or password reset I prefer using Service Objects. For actions that are being repeated through entire model I prefer Form Objects.

I think using either pattern is a great way to clean up and organise your code. After using both of them for a while I came to conclusion that Form Objects are better suited for large projects where Service Objects are ideal for small ones (in terms of processes and object behind the code) or for actions that are rare.



Shameless self-promotion

If you are looking for a place to start learning Ember.js you can try the book I’ve wrote — Ambitious Ember Applications which is a comprehensive Ember.js tutorial. During the course of the book you will build a simple application to help you understand concepts behind Ember.js. After finishing this book you should have enough knowledge to start building complex Ember.js applications.

Next Story — Drag and drop file uploads with Ember.js
Currently Reading - Drag and drop file uploads with Ember.js

Drag and drop file uploads with Ember.js

As I’ve mentioned countless times before Ember.js is really hard to understand and to get it’s concepts right. Without some deeper knowledge knowing how to do trivial things can get pretty tricky. Uploading files with Ember.js using drag and drop is no exception here. Common task to solve which using vanilla stack will only require to include any available JavaScript library for drag and drop file upload may look impossible to solve for some using Ember.js.

Ember.js provides us with View Objects which we will use to solve this particular problem. First thing you need to know is that View Object has it’s own template which can be defined in two different ways.

  1. By creating it’s own separate template and providing View Object with a reference to the template.
  2. By defining a region marked by a {{#view}} block expression.

First technique is fairly simple and is well known. It could look something like this:

<script type="x/handlebars" id="viewTemplate">
<!-- Your awesome HTML codes go in here -->
</script>
App.SomeView = Ember.View.extend({
templateName: 'viewTemplate
});

Second one is a little bit tricky and not so popular among developers I’ve talked to. What you do is you wrap a piece of existing HTML markup (which is a part of another template) into the {{#view}} block expression:

<script type="x/handlebars" id="viewTemplate">
<h1>I am a list of all Files</h1>
  {{#each}}
{{#view App.SomeView}}
<p>{{name}}</p>
{{/view}}
{{/each}}
</script>

This way you won’t have to define a separate template for your view. Now that you know some basic theory behind views lets move to our primary goal — creating a drag and drop file upload with Ember.js.

Lets upload all the files!

As you’ve guessed so far we are going to use View Object to make file upload possible. We will create UploadView with three methods:

App.UploadView = Ember.View.extend({
dragEnter: function(event) {
event.preventDefault();
},
  dragOver: function(event) {
event.preventDefault();
},
  drop: function(event) {
event.preventDefault();
}
})

If we won’t preventDefault() event on these three methods then all the hell will break loose and it won’t work.

Next we need a template. We are going to define it in one that’s already existing:

<script type="x/handlebars" id="someTemplate">
{{#view App.UploadView}}
<h1>I am a list of all Files</h1>
    {{#each}}
<p>{{name}}</p>
{{/each}}
{{/view}}
</script>

Now whenever you will drag/drop file anywhere on someTemplate the methods of View Object will be triggered which at this point will cause default events of the browser not to fire.

First two methods (dragEnter() and dragOver()) are up to you — here you probably want to implement some style changes or some other UI transformation effects to let your user know that he can drop file to start upload. You can select any element inside the view using the following syntax (this particular example will select first paragraph and remove it):

App.UploadView = Ember.View.extend({
dragEnter: function(event) {
event.preventDefault();
this.$('p:first').remove();
}
})

To make uploads possible we are going to extend our drop() method and use XMLHttpRequest. Lets start by defining the backbone of the drop() method:

App.UploadView = Ember.View.extend({
drop: function(event) {
event.preventDefault();
    xhr = new XMLHttpRequest();
xhr.open('POST', '/upload');
}
})

We’d probably want to send files to our server instead of some hardcoded data. We can easily extract files from the event parameter and then send them to the server using xhr.send() method:

App.UploadView = Ember.View.extend({
drop: function(event) {
event.preventDefault();
    var files = event.dataTransfer.files;
var formData = new FormData();
    for (var i = 0; i < files.length; i++) {
formData.append('file', files[i]);
}
    xhr = new XMLHttpRequest();
xhr.open('POST', '/upload');
    xhr.send(formData);
}
})

After you dispatch your data to the server, you will probably create a new record there. But what about the client side of our application? We can easily solve that by adding xhr.onload() method which will fire after the xhr.send() method finishes sending the data and receives answer from the server:

App.UploadView = Ember.View.extend({
drop: function(event) {
event.preventDefault();
    var files = event.dataTransfer.files;
var formData = new FormData();
    for (var i = 0; i < files.length; i++) {
formData.append('file', files[i]);
}
    xhr = new XMLHttpRequest();
xhr.open('POST', '/upload');
    xhr.onload = function() {
App.File.store.push('file', {
id: 1,
name: 'Name'
}
}
    xhr.send(formData);
}
})

Note that inside xhr.onload() method you have xhr.responseText available which contains the response from your server. You can parse it to set attributes of the record you push to the store. Also note that you can push the record to the store in different ways. Here is one of them:

this.get('controller').get('store').push('file', {
id: 1,
name: 'Name'
})

Adding progress bar

Lets expand our View Object a little bit by adding a progress bar to indicate the progress of file upload. First we need to add the progress bar to our template:

<script type="x/handlebars" id="someTemplate">
{{#view App.UploadView}}
<h1>I am a list of all Files</h1>
    <progress min="0" max="100" value="0"></progress>
    {{#each}}
<p>{{name}}</p>
{{/each}}
{{/view}}
</script>

And to update our <progress> element we will use xhr.upload.onprogress() method which will first make sure that event has length that can be calculated and then it will update the value attribute of <progress> element:

App.UploadView = Ember.View.extend({
drop: function(event) {
event.preventDefault();
    var files = event.dataTransfer.files;
var formData = new FormData();
    for (var i = 0; i < files.length; i++) {
formData.append('file', files[i]);
}
    xhr = new XMLHttpRequest();
xhr.open('POST', '/upload');
    xhr.upload.onprogress = function (event) {
if (event.lengthComputable) {
var complete = (event.loaded / event.total * 100 | 0);
this.$('progress').value = complete;
}
}
    xhr.onload = function() {
App.File.store.push('file', {
id: 1,
name: 'Name'
});
}
    xhr.send(formData);
}
})

Now if you initiate upload by dropping any file on the view you will see the progress bar advancing as the file is uploaded to the server.

Final thoughts

As you’ve seen the only difficult part here was to understand Ember’s concepts. Everything else was common stuff. The only caveat here can be the fact that XMLHttpRequest is supported by IE 10+. But in my opinion the time has come to forget the browser which was released three years ago; things changed since then. And the sooner you drop support for
pre-historic browsers, sooner your users will be forced to update their software.

Shameless self-promotion

If you are still struggling with Ember.js you can try the book I’ve
wrote — Ambitious Ember Applications which is a comprehensive Ember.js tutorial. During the course of the book you will build a simple application to help you understand concepts behind Ember.js. After finishing this book you should have enough knowledge to start building complex Ember.js applications.

Next Story — Javascript Form Objects
Currently Reading - Javascript Form Objects

Javascript Form Objects

Riding pesky javascript. The Rails way.


Note: You don’t have to use Rails or any other specific web framework; just modify the javascript code to suit your needs.


TL;DR: switch to any javascript MVC framework. It will save you both time and energy you will waste on reinventing the wheel.


Loading form on a separate webpage, to make edits to a record so you can redirect user back to the previous screen once she is finished, with the full page reload is so 20th century. In 21st century to avoid that behaviour in our applications we use inline edits. Despite the fact that technique is totally awesome (compared to the other techniques available if you are not on a client side MVC), maintaining javascript files behind it can (and in most cases will) become a nightmare.

To make my life easier while working on projects where I am still forced to use vanilla Rails stack, I came with solution I will be talking about today. Otherwise, my advise to you is full steam ahead towards the client side MVC framework — it will make your life as developer easier.

Here is what I will try to do:

  1. Create HTML markup to hold our form,
  2. Create Javascript form object which will be represented by a custom jQuery UI Widget. Inside it we will encapsulate all form logic and handle all form events.

Javascript all the things!

First thing you need to realize is that javascript goes hand to hand with your HTML markup. Messy HTML markup equals messy javascript. Period. In our case we are going to have a container which will hold both HTML representation of a form and the record we are editing itself:

<div data-behavior="parent">
<div data-behavior="expandable">
<p>
Some text that needs to be edited
</p>

<button data-behavior="toggle-form">
Edit
</button>
</div>

<div class="hidden" data-behavior="expandable form">
<!-- Render your form here or leave blank if you plan to
load your form remotely -->
</div>
</div>

Pretty straightforward: we have some text and Edit button inside a container to glue them together. Now we need to make sure that whenever user clicks on the Edit button, the text is hidden and the form is displayed. We will do this by creating a formObject (which will handle all the toggling logic) from specified markup once the user click the button:

$(document).on("click", "[data-behaviour~=toggle-form]", 
function(event) {
event.preventDefault();

formIsCreated = function() {
$(this).closest("[data-behavior~=parent]").
is(":data('ui-formObject')");
};

if(!formIsCreated()) {
$(this).closest.formObject();
}
});

Here we are just preventing the default event (just to be sure no magic happens unless we want it to), validating wether the form object is already created and if the validation passes we create the form object on the element that behaves as parent.

We came to the point where we need a widget called formObject. Lets go ahead and create it using jQuery UI widget factory:

(function($, undefined_) {
return $.widget("ui.formObject", {
_create: function() {
this._on({
});
},

_destroy: function() {
},

_keyup: function(event) {
},

_keydown: function(event) {
},

_toggle: function() {
},

_validate: function() {
}
});
})(jQuery);

This is a basic widget layout with six private methods defined. But what are they for?

Lets start with the _create() method, which is called by default once we create our formObject() by calling $(selector).formObject() — think of it as of widget’s constructor:

_create: function() {
this.element.addClass("ui-form-object");
this._validate();
this._toggle();

this._on({
"click a[data-behavior~=cancel]": function(event) {
event.preventDefault();
this.destroy();
},

"keyup input": "_keyup",
"keydown input": "_keydown"
});
}

Inside the create method we are doing several things:

  1. providing widget with some technical details (such as ID and class name; latter will be used to determine wether widget is created or not),
  2. validating the form,
  3. binding different events to our form.

Yes, that’s right — you can bind any event toggled in you widget or document here and make your formObject() react to it. Unfortunately, we can’t use Rails ajax events (like ajax:beforeSend and ajax:success due to a default behaviour of jQuery UI. To make this work either override a method inside jQuery UI, wait for a fix or register global handlers for desired events and retrigger them with different names without colon inside. Also notice that we bound a click event to the element with the behaviour of cancel; this way we are expecting our form to contain such element — don’t forget to include it in your form.

Next, our _create() method is calling _validate() and _toggle() methods:

_toggle: function() {
this.element.children("[data-behavior~=expandable]").
toggleClass("hidden");
},

_validate: function() {
// Place your validation logic in here. I append data-valid
// attribute to the formObject and set it to either true or
// false for form being valid or not.
},

We need to call _validate() function here because if user is creating a new record, our form will be empty and invalid; so if we are invalidating the form by disabling the submit button, we need to disable it right away.

Inside our _create() method, we are also calling for destroy(), _keyup() and _keydown() events. Lets start with destroy(); we didn’t specify the public method as you’ve may noticed. It is not needed because jQuery Widget offers you one right out of the box. It removes the widget functionality completely and then delegates out to our _destroy() for custom, widget-specific, cleanup.

_destroy: function() {
this.element.removeAttr("class");
this.element.removeAttr("data-valid");
this._toggle();
// I am also cleaning up the form in here — either by
// cleaning out an entire element with a behaviour of form or
// by cycling through inputs and erasing them
},

_keyup: function(event) {
switch (event.keyCode) {
case $.ui.keyCode.ESCAPE:
return this.destroy();
default:
this._validate(event);
}
},

_keydown: function(event) {
switch (event.keyCode) {
case $.ui.keyCode.ENTER:
if (this.element.attr("data-valid") === "false") {
event.preventDefault();
return false;
}
}
}

_destroy() method does nothing fancy — just cleans up the widget and returns it to its vanilla version. _key*() events are separated because different keystates for different keys are handled differently by different browsers under different operating systems (welcome to the 21st century which is different). Note that we are validating our form every time a user releases a key. Also, esc key is bound to destroy the formObject() once pressed. On enter we are submitting our form (only if it’s valid). Keep in mind that you can also specify different key-bindings to different type of inputs or elements, just add “keyup whatever”: “_functionName” listener to your _create() method.

This will work in case our form is local (i.e. it is rendered into to the HTML once the page is rendered). In case form is remote (it is available in a different location from one where user is), we need to fetch it and insert into our formObject().

Here we will take the advantage of the Rails framework and it’s UJS adapter. In case you are not using Rails, you will have to implement your own logic to fetch remote page. First lets alter our markup:

<div data-behavior="parent">
<div data-behavior="expandable">
<p>
Some text that needs to be edited
</p>

<a href="/edit" data-remote="true" data-behavior="toggle-form">
Edit
</button>
</div>

<div class="hidden" data-behavior="expandable form">
</div>
</div>

Now lets make Rails ajax events trigger global events:

$(document).on("ajax:success",
"a[data-remote][data-behavior~=toggle-form]",
function(event, data, status, xhr) {
$(this).trigger("successfullFormFetch", data);
});

Yes, I know, successfullFormFetch is a dumb name and ajaxSuccess would be better but it will conflict with Turobolinks (trollface.jpg). Now it’s only the matter of extending our _create() method and adding custom listener:

_create: function() {
this._on({
"successfullFormFetch": function(event, data) {
$(this).children("[data-behavior~=form]").html(data);
}
});
}

As you’ve probably guessed, we can use the same approach to handle remote form submit (again, if you are not using Rails, you will have to implement your own behaviour here):

$(document).on("ajax:success",
"form[data-remote,
function(event, data, status, xhr) {
$(this).trigger("successFormSubmit", data);
});

The _on() binding:

_create: function() {
this._on({
"successFormSubmit": function(event, data) {
// Logic to update the text. You can even rely on the
// standard Rails JS response here
$(this).closest("[data-behavior~=parent]").
data("ui-formObject").destroy()
}
});
}

Final thoughts

Using this method I’ve managed to get rid of spaghetti jQuery method calls scattered among my application. Now I have a single form.js file where I keep all the logic related to inline edits. It is easy to extend, it is easy manage. Plus with this technique I am getting uniform HTML markup for free.

But as I’ve said before, if you can, run towards client side MVC framework. It will do all the heavy lifting for you (like managing the inline edits).


Next Story — Solving any other problem but the one that matters
Currently Reading - Solving any other problem but the one that matters

Solving any other problem but the one that matters

I live in a wonderful country. That was sarcasm in case you didn’t get it. The problems are everywhere, literally: the government is corrupted to the bone, healthcare is overpriced and dysfunctional, labor is underpaid. Naming it all will probably take to much time. Just think about something (like education, privately held business or municipal sport facilities) — it is not working in this country; it is broken, it is bleeding money, it is everything but serving it’s purpose. It is a problem worth solving and an issue worth fixing.

But we will talk about that some other time.

As you have probably deduced the unemployment rate in the country is pretty high, especially among young people. In attempt to fix the situation government recently passed bill to make an unpaid intership a mandatory for all college students. What’s funny about the situation is that there are no jobs on the market. None. Zero. Null. The reason why fresh graduates are unemployed is not because they have no experiece but rather because there are no jobs for them. To pass the bill is easy, to create new jobs on the market is kinda hard. So why bother — stick to the easier solution.

Once I’ve visited a ruby conference. A guy there was talking about how he implemented a morphologic search in a product he was working on. It was some internal search engine which was performing searches within database of brand names. So if user typed cola-coca instead of coca-cola the system would try and predict the correct query and fix the input for user. He didn’t want to use LIKE queries because: “they are slow.” So instead of single LIKE query the system was splitting string with three different algorithms, looping through each chunk and querying database multiple time during process. Oh did I forgot to mention that there were about 70 brands in the system database?

You probably don’t have to travel far for more examples; look at your company or at your friends company. The heck, entire startup scene or almost any international company or government. Enterpreneurs are trying to solve everything except the single problem that matters. Instead of doing everything to deliver a viable product they are wasting time implementing different yahoo shims into the process of development. Microsoft is bleeding cash supporting sales of their crappy product instead of making a viable one. Developers are falling for whimsical bullshit such as cucumber instead of focusing on writing code that that will fold into the final product.

Although I have to agree that if you can’t solve given problem, trying to solve any other that is even at the slightest similar or related to the one you are stuck at will at least give you a feeling of not being utterly useless. But be honest with yourself — that feeling is completely delusional; by solving made up problems you are not really doing anything of any value.

So next time you have to do something, cut the crap and do your fucking job.

Next Story — The Perfect Window
Currently Reading - The Perfect Window

The Perfect Window

Or why details are important

I live in an old apartment house which was built somewhere between first and second world war. Today, while climbing the stairs up to my apartment I’ve noticed that one of the windows located in the stairwell was opened. One particular detail immediately caught my attention.

Window lock built-in the window frame

It’s only purpose is to lock the window in a opened position so it won’t be slammed by strong wind; a need for such detail can be advocated by the fact that the glass and frame are very fragile and if the window will be shut by the wind with force it will be simply smashed into pieces.


Time passed and we are in the 21st century already. Windows in my apartment, which were recently changed for a new ones, don’t have such a lock built in anymore. I don’t know what was the reason why the detail vanished; was it because manufacturers wanted to cut production costs or maybe because modern windows are made of tempered glass and metal inlays and wont break so easily — I don’t know.

Let’s look at the added value of that simple detail.I live in a windy area (it is located between a river and mountains) and few nights every month a strong wind rises which shuts windows with such force it wakes me up everytime it happens. Few nights every month I spend running around my apartment closing all the windows so then I can try to fall asleep in sweltering heat but without being woken up by a window slams. Well that sucks. A simple detail which costs almost nothing could solve the problem.


Now if we step back, take a look at everything that surrounds us and think how we use these thing in our daily tasks we would probably think of at least one small detail which will make them better. Almost every product that we use daily has the small detail missing which makes the difference between great and mediocre. And it absolutely doesn’t matter if the detail is grey or red, it matters if the details is there and how well it is made and how well it contributes to the product.

Which leads me to conclusion that probably most of you have heard countless number of times: great products are composed of small details. Using different products every day (and feeling great ammount of friction or joy while doing so) just proves it more and more.

Sign up to continue reading what matters most to you

Great stories deserve a great audience

Continue reading