Rails 4.1 was just released this week and I already had a great experience trying out the release candidates on my latest project, so I decided to write a bit about my favorites features on this release and some things I have learned by using them so far.
Placing your configuration in a YAML file isn’t exactly a revolutionary feature, but the usage of the
config/secrets.yml file that comes with Rails 4.1 holds a more important idea: the promise of a default approach for environment aware custom configuration on Rails applications. Over the years the community created several ways to manage such configuration so every app out there deals with this differently, but now we can use the Rails default as a standard just like we do with the app folder or the routing patterns, taking the configuration madness outside the list of things to worry about when working with Rails. So instead of dealing with multiple YAML files or constants left out inside initializers, we can go with the
secrets.yml as the default for our apps.
Remember that you can place any kind of configuration – not just secrets like tokens or passwords – that need to be handled differently through your application environments, like API Endpoints or S3 bucket names. And for any gem maintainers out there, you can make your gem read these settings from the
secrets.yml automagically through an initializer block and maybe remove a configuration step from the gem setup. Adding this to Devise on this pull request was easier than I expected and I suggest you to try it out on your gems as well.
If you want to try to organize your configuration through the
secrets.yml without having to update to Rails 4.1 right now, Andrew White backported this feature on the rails-secrets gem for Rails 4.0 apps.
So, if you are dealing with some configuration mess or aren’t using something like dotenv for your application, I strongly suggest that you try to migrate your config to use the
secrets.yml file and see how it goes for your application.
2) Action Pack Variants
Variants are proving to be a great solution to render device specific views when mixed with any device detection solution like the useragent or browser gems, which you integrate quickly with just a
class ApplicationController < ActionController::Base before_action :set_variant private def set_variant if browser.tablet? request.variant = :tablet elsif browser.mobile? request.variant = :mobile else request.variant = :desktop end end end
Even though the main examples are dealing with User Agent sniffing, this feature can be used in any context where you want to have more control of which views are rendered by your application, like:
- A/B Testing different partials based on the user cookies.
- API versioning for your Jbuilder templates.
- Maintaining current and redesigned views for the same controller.
- Authorization aware views, like
In the end, Variants are just a way for you to have more control over how your views will be used by the app, helping you to remove boilerplate logic from your code and letting the framework handle it through a more elegant solution.
3) The improved cookies serializer
The changes on how Rails serializes cookies are a great improvement when it comes to security and stability of web apps. Before this, any object placed in the cookies Hash would be serialized (and deserialized) through
Marshal.load, which could possibly lead to remote code execution if an attacker got hold on your application secret.
Now this serializer is configurable through the
config.action_dispatch.cookies_serializer configuration option, and new apps will ship with a smarter default: a JSON serializer that won’t recreate complex objects besides Strings, Integers and other JSON data types. And for a smooth upgrade, you can use the
:hybrid serializer that will convert your existing marshalled cookies into JSON cookies, so this upgrade can be transparent for your application users.
This upgrade highlights a possible bad practice in our applications where we end up placing more complex objects in the session that can’t be completely restored by the JSON serializer, when we should be using more simple structures for the data stored in cookies. Thanks to a related issue reported on the Devise issue tracker we could simplify the gem code a bit, so instead of serializing
Time objects we could work with numbers.
So, when updating your application to use the
:hybrid serializer, don’t forget to do a double check of whatever kind of data the app stores in your users cookies and look for possible backwards incompatibility. And if you want to take a closer look on how this was implemented, be sure to check the related issues and pull requests on the Rails repo: #12881, #13692 and #13945.
Keeping up to date with the latest Rails changes
Following the activity on the Rails repository over GitHub helped a lot to understand better these features and the rationale behind their implementations, but going through all the commits and discussions on Issues and Pull Requests would demand a lot of your time. If you want some of the inside scoop but don’t have that much time to go through the Rails activity over the week, Godfrey Chan has put up a weekly digest about Rails named This Week in Rails. I suggest that you subscribe to the list and even check some of the previous editions on the archive page.
Try it yourself!
Take some time and upgrade one of your Rails 4 apps and try out some of the new features! I bet that some of them will help you improve your codebase or make your coworkers life a bit easier, and we are eager to hear from your experience with the 4.1 release.
TL;DR: test quality is not just about verifying correctly whether your code works, it’s also about making your test easy to read and understand. You can do that by structuring your test using the four-phases xUnit standard.
People don’t write tests to be read, they write them to be executed
One of the main reasons to write tests is to have an automated way to check if your code is doing what you expect it to do. That means, trying to verify its correctness. Your test suite acts as a safety net that guarantees your software will continue to work as expected while you refactor, build new features or fix bugs. That’s amazing! But, throughout the years, software developers discovered that tests can be even more than a safety net.
Write tests as examples of how to use your code
A test is an example of how to use your code, not just a way to verify its correctness. Seeing tests as examples of how to use your code changes a little bit the priorities you have when writing them. If the test should serve as an example, then it should be easy to read and understand. Therefore, you should also focus on test readability, not just test “executability” (I know, weird word). One way to improve readability of a piece of text (or code) is to write it in a way the readers are used to, a structure that they expect, some standard way… Let’s think about that.
Back at your school days, you learned that when writing an essay, you’re supposed to structure it in: introduction, body and conclusion. Why? Because that structure helps you to better express your ideas. That means, it helps the reader to understand your message. Is there any equivalent of that for automated tests writing? In fact, there is. It’s called the xUnit structure.
Structure your tests using the xUnit standard
First, let’s see a test that can have its readability improved:
describe Stack do describe "#push" do it "puts an element at the top of the stack" do stack = Stack.new stack.push(1) stack.push(2) expect(stack.top).to eq(2) end end end
One can understand the test above, but still, it’s not easy to quickly scan the test and see that it has logical parts. Those parts would be the the xUnit phases.
The standard xUnit test structure is composed of 4 phases: setup, exercise, verify and teardown.
- Setup: this where you put the object under test in the necessary state for the behavior you want to check;
- Exercise: when you send a message to your object;
- Verify: here, you should check if the object under test behaved the way you expected;
- Teardown: basically where you clean up stuff in order to get your system back to the initial state.
Now, let’s re-organize the test above making explicit that there are different logical parts:
describe Stack do describe "#push" do it "puts an element at the top of the stack" do # setup stack = Stack.new # exercise stack.push(1) stack.push(2) # verify expect(stack.top).to eq(2) end end end
It’s easier to scan, isn’t it?
About the comments, no, we don’t need them. I added them in order to make the example clear. Let’s remove them and keep this structure:
describe Stack do describe "#push" do it "puts an element at the top of the stack" do stack = Stack.new stack.push(1) stack.push(2) expect(stack.top).to eq(2) end end end
One can say that we just added two line breaks, that’s true. But that’s just the how, not the what. The what is: improving test readability. The how is: structuring the code based on the xUnit four-phase standard, by adding two line breaks. Got it?
Using a standard structure to ease the communication of an idea is not something new. As an example, Rails does that when it generates a standard directory structure. When entering on a new Rails project and scanning it, you know your way and where stuff are because you already expect a defined structure and you are used to it. It’s not something completely new, you’re used to that structure. I could also say that even Ruby uses that concept when it talks about the “principle of least surprise”, but maybe I would be going too far. So, let’s get that wrapped up.
Why care about test readability?
So, why should I care about all of that stuff? I mean, isn’t just having my test suite on green enough? No.
Test readability will be really important in a lot of situations. Like when a test gets red, someone needs to fix it. In order to do that, one needs to understand what the test is about. If the test is well structured and easy to read, they can fix it faster.
Also, if you think about your tests as examples of how to use your code, someone that is trying to use a class that you wrote, can see how it’s done in the tests. The test readability will be equally important here too.
So, what about you, how do you improve your test’s quality? How do you improve your test’s readability?
Every once in a while people ask us how we hire and interview software developers at Plataformatec. In this post, we share the key things we do when looking for and interviewing job candidates. We focused the post on actionable hints, from the basic tips up to some specific characteristics to the hiring process at Plataformatec. This is what has been working for us and we hope it is useful for you too.
Part One – define your Candidate Profile
Having a well defined candidate profile can save a lot of your time and is fairly simple to put together. A Candidate Profile makes easy for a non-technical person (an HR colleague for example) to help you find and identify potential candidates. These are some examples of what could be in your profile description:
- common “job titles” (specially if you are using LinkedIn Search to find candidates. ex.: software engineer, software craftsman, ruby developer, and so on)
- the most common skills
- their degrees and/or the universities the candidates went to
- their graduation year (if you’re looking for recent grads)
- companies they have worked for in the past
- also, it helps a lot to describe the things you are NOT looking for
But be careful not to make this list too long, it is supposed to be something simple to use. Our experience says that 4 to 5 characteristics are enough. If you want, you can download a Candidate Profile template at the end of this post.
Part Two – preparing your interview questions
The interview is a great opportunity for you to detect evidences (strong signals) that a candidate would be a great match with your team and that he/she is able to do the job… but you’ve got only 60min to do it. Wow, that’s hard! Where to start?
We’d suggest that you follow these steps:
1) Think about your company Culture and Values
- identify which behaviours…
- …reinforce your company culture
- …are definitely against your company culture
2) Think about the challenges of being in the role/job
- make a list of the key skills that the candidate must have to perform it’s activities
- describe a typical day of a person in this position
- think about the most difficult tasks this position requires
3) Focus on ‘how the candidate solves a problem’ rather than ‘the right answer’
- So, when building technical questions:
- avoid technical questions that are “right or wrong” type
- prefer questions where the candidate has to compare X and Y and present you good arguments (the pros and cons), ex.:
- “When would you recommend using X and when you would use Y?”
- we usually ask the candidates to criticize something that they really like, e.g.:
- “Tell me three things you don’t like about Ruby on Rails.”
4) Test your questions
- once you have finished writing your questions, ask them to yourself, to your colleagues or friends. Take notes about the type of answers you’re getting.
- remember, your job during the interview is to look for EVIDENCES, so if the answers you are getting are not providing you any evidences, then you need to refactor your questions.
Part Three – the interview
All right, you are about to finally meet with the candidate face to face. And if you’re using Skype or Google Hangouts please turn on your camera and ask the candidate to do the same. For the interview here are a few notes and reminders:
- Ice-breaking is important, and so is being nice. There’s high probability that the candidates will be nervous when the interview starts. So, the first step is to make them feel comfortable. This is good for them and for you too. If they feel comfortable, they will be able to be more authentic, show their real personalities. So, it is your job to turn the interview into a pleasant conversation. If the candidate is stressed during the whole interview you probably won’t be able to find any of your evidences.
- Pair-Interviewing. At Plataformatec, we like to interview candidates in pairs because we believe that two people can detect evidences better than just one. Usually one of us conduces most of the interview while the other pays close attention and takes notes. But try to avoid more than two interviewers as it could increase the stress level for the candidate and that wouldn’t help at all.
- The candidate should interview you too. Remember to spare a reasonable amount of time (preferably after you have asked your questions) to present your company to the candidate and to answer her/his questions. It is a respectful gesture. They have saved a few hours preparing and answering your questions and the least you can do is to return the gesture. And don’t forget that they are choosing where they want to work with you too. At Plataformatec, we feel that we had a good interview if the candidates leaves our office with more admiration and appraisal to our company’s culture, even if they are not moving on to the next steps of the hiring process.
- Look for for Cultural Fit evidences. As an interviewer, your job is to detect if there is a fit between the candidates and your company. Sometimes we hear from others interviewers comments like “We scared the sh#@ out of the candidate!”. That is a very corrosive attitude. Besides making candidates uncomfortable and being disrespectful, it is unlikely they will suggest your company to their colleagues.
Well, that’s it. I would love to hear your experiences in this topic and I wish you good luck in finding great teammates for your company!
Hey, there! Here at Plataformatec we like to do project rotations. It means that every three months or so, developers can swap projects. It has lots of benefits like working with different people, getting out of the comfort zone, sharing skills and knowledge, and the best one: a new developer can spot problems that people working for a longer time in the project may not see, since they are used to it.
But, it comes at a cost. Each project has its own setup process and may slow down the development. We’re using Boxen from GitHub to solve this problem. It works very well and allows us to have a project environment quickly set up.
But recently we have run into a problem that Boxen couldn’t solve. We had a project which has multiple repositories and some of them are too large. It would take some time just to git clone their > 3GB size repos.
Our first thought was creating a tar file with gzip or lzma compression. The problem with it would be when extracting, since file ownership and permissions on it could be a problem just like symlinks. So, the solution was to git clone the smallest repos and git bundle the larger ones. Git bundle is shipped with git, but only a few people know about.
The workflow we have is simple. Someone with the repo already cloned and updated to the origin, type the following command:
$ git bundle create <repo name>.bundle master
It will create a file called
Now that you have the file in hands, it requires two steps to work properly. The first one is extracting the bundle into a cloned repository. This can be achieved by:
$ git clone <repo name>.bundle -b master
In case you want to clone into a different path other than
$ git remote show origin * remote origin Fetch URL: /path/to/<repo name>.bundle Push URL: /path/to/<repo name>.bundle …
It is pointing to the bundle filename, so every time you fetch or push, it will try to do so in this bundle file. To fix that, we go to the second step which is setting the proper remote URL.
$ git remote set-url origin <repo url>
That’s it. You’re ready to go. If you have multiple repositories to share, you can create a script to automate the cloning and the url setting for the origin. You can share all the repos with this script, for faster and easier setups.
The Ruby language repository size is about 200MB. It is not big enough to require a bundle, but just as an example I guess it would be a nice fit.
The first step is cloning the repo:
$ time git clone https://github.com/ruby/ruby.git Cloning into 'ruby'... remote: Finding bitmap roots... remote: Reusing existing pack: 269821, done. remote: Counting objects: 2813, done. remote: Compressing objects: 100% (1403/1403), done. remote: Total 272634 (delta 1707), reused 2213 (delta 1390) Receiving objects: 100% (272634/272634), 136.77 MiB | 1.20 MiB/s, done. Resolving deltas: 100% (210263/210263), done. Checking connectivity... done Checking out files: 100% (4187/4187), done. real 4m51.501s user 1m38.837s sys 0m18.808s
As you can see, it takes almost five minutes to clone the full repository – the time may vary depending on your bandwidth. So, now we’re gonna create a bundle file and then clone a new repo from it:
$ cd ruby/ # Just a reminder, the main branch of ruby repo is not master, it's trunk. $ git bundle create /tmp/ruby.bundle trunk
Now that we’ve created a bundle file and placed it in /tmp, we just need to clone it:
$ cd /tmp/ $ time git clone /tmp/ruby.bundle -b trunk ruby Cloning into 'ruby'... Receiving objects: 100% (206590/206590), 84.16 MiB | 22.43 MiB/s, done. Resolving deltas: 100% (158583/158583), done. Checking connectivity... done Checking out files: 100% (4187/4187), done. real 0m46.490s user 1m9.339s sys 0m10.021s
Cloning from a bundle file was much faster and has not taken a minute. Now, in order to pull and fetch changes, you need to set the remote URL:
$ git remote set-url origin https://github.com/ruby/ruby.git
Enjoyed this post? Was it as useful for you as for us? Tell us your stories on the comments below! See you!
There is a XSS vulnerability on Simple Form’s label, hint and error options.
Versions affected: >= 1.1.1
Not affected: < 1.1.1
Fixed versions: 3.0.1, 2.1.1
When Simple Form creates a label, hint or error message it marks the text as being HTML safe, even though it may contain HTML tags. In applications where the text of these helpers can be provided by the users, malicious values can be provided and Simple Form will mark it as safe.
The 3.0.1 and 2.1.1 releases are available at the normal locations.
If you are unable to upgrade, you can change your code to escape the input before sending to Simple Form
f.input :name, label: html_escape(params[:label])
To aid users who aren’t able to upgrade immediately we have provided patches. They are in git-am format and consist of a single changeset.
Thank you to Paul McMahon from Doorkeeper for reporting the issue and working with us in a fix.
It has been reported that malicious users can do e-mail enumeration on sign in via timing attacks despite paranoid mode being enabled.
Whenever you try to reset your password or confirm your account, Devise gives you precise information on how to proceed, if the e-mail given is valid, if the token has not expired and so on. This means that, by trying any given e-mail, a third-party person can know if a particular e-mail is registered in that website or not.
While this is not a problem for many applications, some applications would like to keep their user information completely private, even if it means loss of usability on features like account confirmation. For such use cases, Devise supports something called paranoid mode, which has been reported to still be vulnerable to enumeration on sign in.
Only applications using Devise paranoid mode need to update. New releases have been made for Devise branches 3.2 (3.2.1), 3.1 (3.1.2), 3.0 (3.0.4) and 2.2 (2.2.8).
Users running on those branches and cannot upgrade immediately can fix this issue by applying this patch. Users running on older versions are recommended to upgrade to a supported branch immediately.
We want to thank Tim Goddard, from YouDo Ltd for reporting the issue and working with us on a fix.