Skip to Content

About: Marco Gallardo

Marco Gallardo

Recent Posts by Marco Gallardo

Rails basic API authentication with Sorcery and JWT

APIs have become more and more popular due to increasing demand for development of mobile and single page apps, and so the need of sessionless server-side applications, being those that are token-based the most popular ones now days due to their relative easy implementation. Here you have a great example that uses JWT to secure a microservice-based application.

JWT (or jot) stands for JSON Web Token and as it states it is a web token structured in a JSON format. JWTs are composed of 3 parts: the header, the payload, and the signature. In short, the header contains the type of token and the algorithm for the cryptographic signing; the payload (or claim) contains the information wanted to securely send to the server, and the signature which contains the secret key known only by the server and that is used to decrypt the data contained in the payload. It is not the primary objective of this post to explain in detail what JWT is, so if you want to know more about it you can do it here.

JWTs are used in the next way:

  1. The API server generates the JWT.
  2. The JWT is sent to the client.
  3. The client saves the JWT (i.e. in LocalStorage).
  4. The client sends the JWT back –we’ll send it on a request’s header– to the server.
  5. The server uses the JWT’s payload data for X or Y purpose. In our case to identify the user that is performing the request.

 

Besides JWT, we need an authentication strategy to actually identify users. We’ll use Sorcery for this purpose; I recommend you to go ahead and read the documentation if you haven’t done so. You can implement any other authentication library –or build your own– but for this particular case I personally like Sorcery because it offers all basic authentication features and it is not as overkilling as other libraries.

This is how the general authentication flow looks like:

jwt-diagram

Fig. 1 JWT Flow

Conveniently there is a jwt library that we can use to generate user’s token, so go ahead, read its documentation and install it in your project.

Next, we’ll create a service to provide the JWT, another one to validate it, and a last one to authenticate the user.

app/services/jwt/token_provider.rb

app/services/jwt/token_decriptor.rb

app/services/jwt/user_authenticator.rb

NOTE: In this case we are assuming that JWT is in ‘Authorization’ header with format ‘Bearer xxxx.yyyy.zzzz’, that’s why we are splitting @request_headers['Authorization'].

Implementing our services

We need to generate the JWT after user has successfully logged in:

Or signed up:

The token returned in the response should be properly saved in the client so it is sent back to the server in subsequent requests’ headers.

Then we need to authenticate user on future requests. Adding an authentication method on ApplicationController will let us use it on ApplicationController’s children controllers to protect our private endpoints:

And that’s it, our API is now secured using a sessionless approach. From this point on you can add more complexity using jwt and Sorcery‘s methods to, for instance, make token expire after 1 hour or reset user’s password.

Let me know in the comments section below what you think about this strategy.

0 4 Continue Reading →

Long live your app: MongoDB Replication

The scenario

Not so long ago a customer requested that we provide the highest server reliability that we could. The application was pretty big, with about seven servers per environment. We needed to increase reliability in web servers and databases. In this article, I’ll explain how we achieved that from the database side.

While searching for options, we found that MongoDB (which was the database engine we were using) offered several options that increase your database reliability, i.e.:
MongoDB – Sharding
MongoDB – Replication

We went for MongoDB Replication –also known as Replica Set– because our customer needed a solution ASAP, and the configuration needed is minimal. Besides, it offers whole database replication, which we needed to implement other security measures, like backups.

Enough context for now, so let’s jump into the action!

Configuring MongoDB

First, it is important to notice one thing, as the name states, MondoDB’s Replication will be copying your database ‘n’ times (once for each replica member). With that said, to obtain the maximum benefit from this practice you will want to have your replica set distributed in N different physical servers (i.e. Ubuntu servers). We’ll explain how this works below.

Having N servers set and ready only to practice could be expensive and time-consuming. Therefore, we’ll be performing all of the examples on this article in one single server –your computer– to allocate all of the replica’s members. And we will be creating different folders and pretend that each one of them is a path to a different physical server. So let’s create folders that will be hosting each replica’s member. In our case, our DB’s path is under ‘/usr/local/var/mongodb/’, so we’ll create three folders (a replica needs at least three members) under that route:

If you don’t have your database’s path, you can get it by running this in MongoDB’s terminal:

Within the output command above, locate “dbpath” inside “parsed”.

Example:

With our fictitious servers ready, the next step is to create three “mongod” clients (one for each replica set member).

Note: you need to leave each client running, so you might want to run them in background by appending an ‘&’ at the end of each command. If you need to bring those commands to the foreground, then execute ‘fg’ in the corresponding window where your background jobs are running. Here is an example of how to run mongod clients:

Explaining commands:

mongod: executes mongodb.
–port: indicates the port that the mongod client will be listening to.
–dbpath: specifies the path to your application’s database. In our case, this is pointing to the directories previously created.
–replSet: sets the name of the replica set.

Now you can connect to each mongod client to start configuring the replica set!

Configuring your Replica Set

To configure your replica set, first you need to be connected to one client. You do it by executing the ‘mongo’ command in your terminal and append the –port option to indicate which client you want to be connecting to. In our case, we will be connecting to our client with port 27018:

Once connected, we can start configuring our replica set.

Defining Replica Set Configuration

Configuring the replica set is pretty simple and straightforward, all we need is to set some basic parameters. Go to the mongo shell you just opened and type:

Explaining options:

rsconf: the name of the object or variable that will contain the replica set configuration.

_id: sets the name of the replica set. This needs to match the –replSet option that you set when executing the mongod client. In our case: rs0.
members: sets all the elements that will be conforming our replica set. Elements should be contained within and array following this format:
member’s _id: the element’s identifier
host: the ip address of the server that is hosting the element. It has to be followed by the port where the mongod client is listening to.

Now, apply the configuration to the replica set. In the Mongo shell, type the following:

If everything went OK, you should see this:

You can see additional information by executing rs.isMaster().

At this point, your replica set is up and running!

So you might be thinking now, “so far so good, but I haven’t seen any real advantages yet…”

Let us explain a bit more. What makes MongoDB Replication a good strategy to increase your app’s reliability is the fact that your database will be always available for your web application. You might be wondering ‘How is that possible?’ As you might be guessing, having your database replicated N times gives you the opportunity to prevent data loss and sustain a persistent connection between your database and your web app.

MongoDB Replication consists on having a database replicated N times, where one element is the Master/Primary (this is the only one interacting directly with your app) and the rest of them are Slaves/Secondaries (these are interacting with the master).

This is how it works: when the master element dies, MongoDB automatically chooses a slave element and turns it into a master that will be accepting all IO operations. Your database will be always ‘alive’.

Browsing Secondary elements

You can see your replica set slave elements by logging into a mongo shell for each one of them and typing rs.isMaster(). Don’t forget to set the –port option like this:

Once you are in the mongo shell, the first indicator that you will see is:

Then, after you executed rs.isMaster(), you should see something like:

Where “ismaster” and “secondary” will tell you that that specific client is an slave element. Also, you can see that “primary” option is indicating the IP address of the element that is the master.

And that’s it! You are done configuring MongoDB! Continue next to see how to configure your Rails app to make it work with the replica set.

Configuring the Rails application

If you do not have a Rails application created go ahead and create a new one. Since we are not going to use ActiveRecord, you can append –skip-active-record to the “rails new” command to skip ActiveRecord’s installation and configuration.

Once you have the new Rails app, you will need to include Mongoid in your Gemfile and execute “bundle install”.
Execute “rails g mongoid:config”. This will create config/mongoid.yml where you will have to add the configuration for your app’s db. The configuration of this file is a little bit different than usual, so here you have an example of how it would look for our exercise:

As you can notice, the three hosts are the MongoDB clients we created at the beginning; make sure they are still up and running.

After configuring mongoid.yml, go ahead and create a controller, a model and some views. You can use “rails g scaffold” to speed up the process ;). In this case, we are going to create the basic CRUD for users.

Now go ahead and start the Rails server and add some information in your app.

Checking that MongoDB Replication is working.

Now we are ready to test our replica set, we need to log into the three mongod clients:

Inside the client with port 27018 (the master) check that the database you set inside mongoid.yml was created:

You should see the database you used in your mongoid.yml, in our case we have this:

Then select your database, in our case:

And check that the information you captured in your web app is there:

You should see the data you entered through your web application, in our case:

Now go to the slave elements and repeat the process; you should see the same info that is persisting in your master element. Note: when trying to execute “db.users.find({})” you will receive a restriction error message, that’s normal, go ahead and execute:

NOTE: By default MongoDB protects all the info from being read, so with rs.slaveOk() you are telling MongoDB it is OK for an external user to have access to stored data in the replica set.

Testing database reliability: kill the master

Let’s put al of this to a test. Go to your mongod clients and identify the master. If you don’t remember which one is your master, login into a mongo shell of any of the mongod clients and execute “rs.isMaster();”. In the output, look for the field “primary” to get the IP address of the member that is currently the master/primary.

Our master element is the client running in the port 27018, so we will kill it by executing the following:

Now, go back to a Mongo shell and execute rs.isMaster(). In the output, you should see under “primary” that a new member replaced the one that is dead.

Is my application still working?

Go to your browser and enter new information. Everything should be smooth and quiet as usual, your web app is working correctly.

Reviving the dead member

Once you know your web app is still up and running, then go back and execute the mongod client you just killed in the previous step, in our case:

and log into a Mongo shell for that client:

As you may notice, this member is not longer the master; another member has taken its place and has let it with a secondary role. If you want to know which is the new primary you can use rs.isMaster() again and identify who is the new master.

But what happened with the info save while this member was gone?
Let’s look for it. Connect to the member you just revived and execute next:

You will see all the information that was added through your web app when this replica member was down:

How cool is this?!

Reconfiguring MongoDB Replication

You might have noticed that even if you kill all mongod clients, the next time you execute them the replica set will still be there. Why is this? Do you remember the output when we executed the command rs.initiate(rsconf)? It read something like:

Yes, the configuration was saved! Therefore, every time you execute mongod clients using the –replSet and the same replica set you used before, then that configuration will be applied for that replica set.

Changing, removing, or adding a replica set member is not too hard. Connect to a mongo shell for the primary mongod client, and set a new newConfig object containing all new members, and then apply those changes with:

That’s it! Now you know all the basics of increasing the reliability of your web application by setting up MongoDB Replication!

Conclusion

A downside to MongoDB replication is that it does not matter if your database is replicated N times on N servers, it is still being centralized. Which means that you could bump into networking performance issues if you do not provide your server with enough resources (RAM, processor, hard drive space) to handle your data.

But! Even in spite of the issue mentioned above, we still believe that MongoDB Replication is a good option when you need a server that is reliable, easy to configure, and fast to set up. If you want to learn more about this technique and squeeze all the power of MongoDB Replication, we recommend you read the official documentation to see all the configuration options you can use. For instance, you could set a hidden replica member to create a backup file of your database and upload it to an AWS S3 bucket!

Thanks for reading! Let us know what you think in the comments.

M.

0 5 Continue Reading →

Don’t let working remotely ruins your performance

Certainly, the concept of ‘remote work’ sounds very tempting…

Ill

(Photo credit: Jan Kaláb)

… but don’t let that fool you! Working remotely is a double-edged sword.

I have found three main areas you need to take care of if you want to stay productive while working remotely: discipline, communication, and time zones. Keep reading to see why I am saying this, plus some tips that will prevent you from performing poorly. And who knows, perhaps you’ll end up having a better performance working remotely than if working onsite.

Discipline

I remember the first time I worked remotely, it felt awesome! I could start or pause work at any time I wanted. And that feeling of freedom, of being able to go to the kitchen and grab some food, watch some TV if I got bored… it was great. I used to wake up at 9:00am, have breakfast, take a shower, and then start work at 10:00am. At this point I was running an hour late, if we compare it with a typical office schedule.

It didn’t take long before I found myself working the whole day. Starting at 10:00am, making frequent breaks, plus doing all the chores and errands a normal person in his twenties has to do. The result: I ended my work days at 12:00am… I had turned into a slave of the freedom that I had.

The solution

You need to take remote work as seriously as if you were working onsite. Remember, with so much freedom it might not seem like it is the same, but you still have have a job to do!

Obviously, taking breaks once in a while does not hurt, but I recommend you avoid granting yourself too much freedom until you have mastered your procrastinating nature. It’s possible to tell if your impulses are under control after a couple of months of working on it, tracking how successful you have become at achieving your goals. And yes, you read right, it takes months. It has been proved that it takes over 2 months of daily practice to develop and establish a new habit.

If it is very hard for you to be disciplined, there are some tools available out there that could help you keep focused on work. A very popular (and effective) one is the pomodoro technique. This time-management method can help you improve your focus and mental agility. Pomodoro promotes work intervals that last 25 minutes, and are alternated with 5-minute breaks, thus increasing your productivity. I have tried it myself and it works, it structures your work day in a way that makes you spend your time more efficiently.Try it out yourself and see if it brings any positive changes to your productivity.

Communication

When I started working remotely I was in charge of a team of 3 people. As you can imagine, not only was my own performance compromised, but also that of my team and project’s. Unread emails and messages were something I had to deal with every day; slowly but surely this was something that was affecting our work deliveries.

The solution

Remember, when you work remotely, you aren’t really alone. You have co-workers, clients, supervisors and other people you work with. Because of this, it is very important to share your status frequently. You can decide on different strategies with your teammates. These are some I personally prefer:

1. Email at the beginning and at the end of the day. I recommend this specially to improve communication with your client. Generally, they are very busy during the day because they have very tight schedules. A good practice I like keeping is sharing my work plan for the day with the client, using the following Scrum-based format:

  • What I accomplished since yesterday:
    • goal 1
    • goal 2
    • goal n
  • What I’m planning to accomplish today:
    • goal 1
    • goal 2
    • goal n
  • Impediments:
    • list the stuff that prevented you from achieving a goal

 

2. Use text messengers appropriately. Use them concisely and only when communicating important stuff to your teammates, you don’t want to interrupt them frequently as you don’t want to be interrupted often either. Here are some examples of things worth communicating and how to do it briefly:

  • ‘A bug appeared in production…’,
  • ‘I finished the feature…’
  • ‘I would like to know the status of…’
  • Or simply ‘I am leaving!’, so everyone is aware you won’t be available from that moment on.

 

3. Keep project management tools updated. Some PM tools allow the addition of comments inside stories (also known as tickets). I recommend you to keep your stories updated by adding a comment with an status whenever any of the following happens:

  • You hit a milestone while building a feature.
  • You have made progress solving a bug.
  • You are going to perform a chore.
  • You are stuck.

 

This way, the client and your teammates know what’s the progress on that story. You will help others to determine if the committed work is in risk of not being delivered, and you can receive help to speed up your work.

Beware of different time zones

This is perhaps the least harmful of the three, because it does not affect your work directly, but it can be a rock in the shoe. I didn’t know this was going to be a constant pain until I started working remotely. I had to deal with 3 different time zones: our customer was on PST, my co-workers on CST, and I was on EST. I was 3 hours ahead of our customer and 1 from my co-workers, and this brought communication issues. When any of them tried to contact me it was very likely that I had already finished my work day.

The solution

Be sensible when arranging meetings, inform others the time when you usually have lunch. Let them know at least one week in advance if you are going to take days off (including those you take for religious reasons, if that’s your case). It took me about 4 weeks to get used to all time zones and to adjust my personal schedule, sometimes having to move my lunch time an hour earlier or later, but at the end it was worth it.

Other good practices

Here at TangoSource we are proud of our remote work practices. We summarized best practices for remote work on our playbook so that anyone can work remotely effectively. Here are a couple of examples:

  1. Create a daily routine list. This list contains recurring action items that you will be checking at the beginning, during, and at the end of the day. An example of a daily routine is: checking and answering emails at the beginning of the day, check messenger apps during the day, and sharing your status at the end of the day.
  2. Create a weekly routine list. This list contains all action items that you will need to take care of during the week. Example: meetings, days off, deployments to servers, etc. Having this routine will help you to have a well-organized schedule.

The conclusion

It took me four to five months to master the three areas mentioned above. If you’re struggling to deliver results while working remotely, or if you’ve never done it and are afraid to try, well, now you know what to do. Put these ideas in practice, don’t give up, and soon you’ll be ready to work from the Caribbean!

Are you interested in learning more about TangoSource and having us as part of your development team? Shoot us an email! We would absolutely love to hear from you! 🙂

by Marco Gallardo: Email / Github

2 8 Continue Reading →

Testing your application on IE with Mac OS X

Today I’d like to show you how to test your web apps on Internet Explorer by binding a Virtual Machine running Windows with Mac OS X. I’ve learned to do this by experience and I thought some people might find it useful.

What I will cover:

  1. Binding the Virtual Machine with Mac OS X
  2. Testing once you have setup VirtualBox.
  3. Fixing CSS3 and HTML5 compatibility

 

So, let’s get started…

Binding the Virtual Machine with Mac OS X

  1.  Install virtual box on mac (https://www.virtualbox.org/wiki/Downloads)
  2. Create the partition and install Windows in your VirtualBox machine, this is going to be your Guest OS (Windows). You can follow this guide to see how to do it.I recommend assigning 4GB of RAM to your VM if possible, otherwise it could run very slow.
  3. You need to be sure that your Guest Machine’s network adapter is attached to the NAT and to do so, go to your VirtualBox app in the Host OS (Mac OSX) and then click on “settings”, after that click on “network”. Make sure that NAT is selected in ‘attached to’ field.

There are two ways to check the address of the application:

Using Pow

This is the the approach you have to follow if using domains and subdomains is a requirement in your app.

  1. Install Powder gem in order to link your projects and navigate on the browsers as “real” domains. Open your terminal and go to your project and code “gem install powder” then “powder link”. Now your application is available at http://your-app.dev/ finally open your application with “powder open”
  2. In order to see the application with the “real” domain you have to add an item to the hosts file. Go to your Guest’s OS and add the host to the list.Here’s how: http://www.rackspace.com/knowledge_center/article/how-do-i-modify-my-hosts-file

Without Using Pow (two ways)

You can use your Host OS’ IP address directly to configure your Virtual Machine doing this:

Using the IP directly
  1.  Go to your “terminal” in your Host OS (Mac OS X) and type “ifconfig” in order to get the ip (copy the ip next to the “inet” word in the “en1” block).
  2. Copy the ip in the address browser with the port that you are using. For example: http://192.168.1.212:3000 (where 192.168.1.212 is the IP address and 3000 is the port where my app is running).
Assigning a static ip to the guest OS (recommended)

I recommend this option to avoid having to look at your IP address every time you are running your Virtual Machine.

  1.  Follow instructions on this link. If you don’t find the vboxnet0, check how to fix it on this link, and if you have an error trying to add the vboxnet0 network then execute this in your Mac terminal: sudo  /Library/StartupItems/VirtualBox/VirtualBox restart.
  2. Now check that your Guest OS is linked to your Host OS by typing the next IP address in your Guest OS browser’s address bar: 192.168.56.1. If everything worked you should see your Host OS’ localhost (make sure your localhost is running in your Host machine).
  3. As a fancier option, you can do this: in your Guest OS click on the Windows icon and then do right click on Notepad; select Run as administrator. In Notepad click on the File menu and then Open, after that paste C:\Windows\System32\drivers\etc in Notepad’s address bar. Once you are in \etc select the All files option so you can see the host file. Select host file and click open. Add an alias for 192.168.56.1, that way you can use domains in the Guest OS’ browsers instead of using the IP address. Don’t forget to specify the port right after the new URL in your browser, e.g. http://mylocalhost.com:3001.

 

As a final tip, pay attention to browser’s address bar if you are working on a project that is composed by several apps using the same domain. You have to make sure that you remain always under the same domain (the one you added on your host file in your Guest OS), otherwise communication between your apps will break. In my experience, I was working on a project that apparently was not working, but that was because requests from myapp.com:3000 were not being delivered correctly to myapp.com:3001 and the issue was that myapp.com:3000 was sending requests to anotherdomain.com:3001.

Testing after setting up VirtualBox

Testing and fixing styling issues is not that hard. Next I’m going to mention some libraries and tips that will help you to fix cross-browsing issues.

  1. Install utilu, which allows to have multiple standalone versions of the IE browser. Also install IE9 on your Guest OS.
  1. Open the website on IE and Google Chrome then make a comparison between them. Try to identify two main things (navigate through the application page by page), functionality and styling. Functionality could be video playing function, clicking a button and seeing what happens, styling could be that the buttons are in the wrong place, the border looks different, etc.
  1. Navigate through the application page by page and take screenshots of the issues that you find in the revision if they are styling issues. It there are functionality issues then write a description about what the bug is and how to reproduce it (it could be an issue related to Javascript for example).
  2. When you are navigating page by page start the debugging mode on IE, pressing F12 and then selecting the “script” tab. Look for errors related with Javascript that could break your loading page. Also, can check the HTML, CSS and network outputs in order to see if something is wrong.
  3. If you already detected the differences, I recommend you to write them down so you can track them. Since I use pivotal what I do is to open a new ticket for each issue I find.
  4. If you already tested the application on IE9 you can also check the application on “compatibility mode”, to simulate the IE8 version with IE9 by selecting “document mode: IE8 standards” and “browser mode: IE8’. Those options are in the developer tools window (see screenshot).

 

IE developer tools

IE developer tools

 

Now you can test your application on IE7 to IE8, just one thing to keep in mind: what you will see is not an exact copy of what you would see if you installed IE8 or IE7. It is only an approximation. It can help you detect some bugs in a easy and fast way. It’s better and recommended to install the real version or each browser and test the application there.

Fixing CSS3 and HTML5 compatibility

  1. If you detect that some elements (buttons, inputs, text) are in the wrong place, you could check the HTML code using “developer tools” from IE browser (pressing F12).
  1. Inspect the element that is malfunctioning and see the HTML code, check that the code is correct. Remember IE8 doesn’t support HTML5 tags. Like this one:

This is the code that you expect:

<header>I’m Header Text</header>

This is the code that you really have on IE8:

</header>

To solve this problem you can include HTML5 Shiv library inside of your <head> tags.

<!--[if lt IE 8]>

<script src=”html5shiv.js”></script>

<![endif]>

The next example shows how the site looks when you are and when you are not using this library.

Difference between Shiv and Pie

Difference between Shiv and Pie

  1. The next step is checking the CSS3 properties. As you probably know, IE8 doesn’t have the same rules as Moderns browsers, IE8 doesn’t support css3 properties. The solution to fix this kind of issue is installing Pie as a JavaScript library (same as the shiv library inside of <head> tags). In this way we are going to be able to use properties like border-radius, box-shadow, etc.

 

NOTE: bear in mind that those libraries help to improve the style of your website and make your site more compatible with IE, but there are some little variants. For instance, in the box-shadow tag it is not possible to add alpha transparency because it is not supported by the library.

The left image shows how the site would look with the Shiv and Pie libraries.

The left image shows how the site would look with the Shiv and Pie libraries.

  1. Speaking of functionality, you have to check the behavior of your application and make a comparison and fix one issue at the time. Try to be patient and get help from the “developer tools” that IE provides.

 

Some notes:

  1. Look for errors in the “script” console of the developer tools.
  2. Remember that IE does not support some Javascript methods because it runs an old JS version.
  3. Remove “console.log”, it could break your code.
  4. If you are working with videos you can use video.js in order to make videos compatible with IE, using fallbacks. Remember, use a link when flash is not installed instead of an image.
  5. Test your application and make comparisons about the missing elements, and also test in modern browsers because you could break your code without noticing.

 

Well, that’s it! I know it was long but I think it can help someone out there. Please let me know if you have any feedback in the comments section below.

Special thanks to Jaime Gonzalez, who contributed with the creation of this article.

0 4 Continue Reading →

What? Rails can’t hear you? Use Flash!

First I’d like to mention that this post is not for beginners, that means that I’m assuming that you know about programing with Ruby on Rails (for this post I’m using Rails 3.1) and some of Javascript. If you don’t know Rails or JS at all, you may need to do some research about the terms and instructions I say here. With that said, lets start!

Have you ever needed to record and save user’s audio by using computer’s microphone using Rails? If so, I bet you realized that there is almost no information about how to do this using Rails.

The Story

I was working in a project where the customer needed to implement a feature to allow users to record his voice by using his computer’s microphone. I thought “this can’t be that hard, there is HTML5 now,” but I had no idea what I was talking about.

Researching: HTML 5 or Flash?

I started researching about HTML5 and it didn’t take me that much to see that HTML5 is an “still in progress work“ when it comes to record live audio. The browser that currently has the best implementation for HTML5 audio tag is Chrome, and yet it needs the user to configure some of its flags for this tag to work properly, so I discarded HTML5 as an option.

I continued researching and soon I started reading in many posts that the best approach to accomplish what I was trying to do was by using Flash in the client side. I know, I don’t like Flash either, but lets face it, most browsers support Adobe plugins and this is better than having the application working only in Chrome, so I decided to give it a shot, and took the Flash & Rails path.

Once I decided to go with Flash, the next impediment I had was that I’m not a Flash programmer, but that was solved when I bumped into the jRecorder plugin (I want to thank to Sajith Amma because he certainly saved me hours learning Flash). jRecorder is a plugin that uses a Flash object to get access to user’s microphone and records the microphone input. This plugin has also an API built in javascript to initialize and interact with the Flash object.

Ok, enough background, let’s jump into the interesting part:

Coding

Download the jRecorder plugin, and unzip the file. You’ll see 7 files; the ones we need are: jRecorder.js, jRecorder.swf, and jquery.min.js

In your Rails application:

Explaining the code

This is the DOM’s object where the flash object will be inserted.

The js code is actually the constructor of the js object that will interact with the Flash object (we can say it is a sort of an API). You can read the documentation of the plugin here, however there are 2 parts that I would like to explain since the example that our good friend Sajith implements is in PHP and you may get confused:

In ‘host’ we are defining the route where we want to receive the recorded audio, in this case, for my application <%= audio_path %> points to a controller named audio in the action upload_file that we’ll use to save the audio file. You can create a different route, just make sure it uses the POST method because we are sending information to the server, and filename=audio.wav is a parameter that contains ONLY the name (that means NOT the recorded audio). The result of “<%= audio_path %>?filename=audio.wav” would be something like ‘/audios/upload_file?filename=audio.wav’.

The other interesting option that you need to translate in the example from PHP to Rails is ‘swf_path’. This option is where you set the path of where jRecorder.swf object is located, and all you have to do is to use Rails helper ‘asset_path’ and pass to it the name of the flash object.

At this point we are done with the client side.

Jumping into the backend

Go to the controller that responds to the route that you specified in ‘host’ parameter in the js code, in my case it’s the action upload_file in audios_controller.rb. If you already read the jRecorder documentation that means that you’ve seen this:

(PHP code)

This code is very self-explanatory and you can infer that all this code is doing is receiving the recorded audio, opening a file, writing the recorded audio, and closing the file. Now, what is the equivalent code in Rails? Here it is:

The interesting line here is ‘request.raw_post’. That line contains the actual audio recorded by the user that was sent by our view using the plugin. That line is the equivalent of ‘file_get_contents(‘php://input’)’. Also check that we are opening the file with ‘b’, which is very important because the file we are reading/writing is a binary file (otherwise you’ll face encoding issues).

That’s it! You should now have the file stored in the root path of your application!

Improve it

Depending on your application, there are many things that you can improve, like converting the file from .wav to .mp3 or .aac formats using Zencoder, uploading the file to S3 buckets, implement background jobs to save the audio, etc.

Got questions?

Let me know in the comment section below.

0 0 Continue Reading →

 

Recent Comments by Marco Gallardo

    No comments by Marco Gallardo