I'm a Floridian web engineer who planted his roots in Paris. Some of my favorite past-times are analyzing and optimizing development processes, building solid APIs, mentoring junior devs, and long walks on the beach.

Internationalize your rails app 08-19-2018

I18n - Expected usage after setup

If everything has been properly put into place, then we expect to be able to simply use the t method in our views and have them render in different languages:

<h1><%= t('some.string.value') %></h1>

/// Should render:
<h1>My Value</h1>
<h1>Mi Valor</h1>
<h1>Ma Valeur</h1>

Stateless requests

If we don't know too much about the inner workings a few of the first roadblocks will be dealing with moving between requests. How to we store the locale between requests? How can we store anything between requests?

Cookies

I've actually used this for a simple wordpress site I had. The user carries the cookie with them, so once they choose their locale, it stays with them. It is dirt simple to set up, but there are a few drawbacks.

  1. You can't share locales when sharing a link, since the locale is attached to a user, if you have a spanish user sharing a link, the locale will change back to the default when the link is followed by another user. This is because the locale is tied to the user's browser.
  2. Signing out loses the user's locale setting or at least complicates keeping it
  3. Storing the locale in a cookie will make it harder to reason about. This seems like a minor thing, but when bugs come up dealing with a locale, you will be happier having it in directly in the URL.

URLs

Storing your locale information in the URL is probably the most straight forward. It takes a little more plumbing to implement because since it will be stateless, you'll have to ensure that every link contains the information.

However, it is explicit as it is visible in the URL. It is shareable and debuggable for the same reason.

Where to put my locale

Rails has a few things to say about this but essentially you have a few different possibilities for keeping the locale in the URL.

  1. Subdomains(http://fr.wollydo.com/machins) - can be beneficial if you want to think of each locale as a different site, and it is more cost effective than a TLD
  2. Top Level domains(http://wollydo.fr/machins) - are another way to designate locales as different sites however, you need to buy each domain.
  3. URL parameter(http://wollydo.fr/machins?locale=nl) - a little planned way to keep the locale in the url.
  4. URL path(http://wollydo.fr/fr/machins) - this treats locales as the most important identifier of the site, by putting it first in the path. It is a much more permenant decision than a simple parameter because you have modified your path structure.

I am going to assume that you think that the last option is the best. The rails guide actually has quite a bit of helpful information if you want to look into the other locale options.

Life of a rails request

Here is the life of a rails request for an app that has a machins resource.

Simplified life of a rails request

With this simplified view of the path of a request, we can see that to handle communicating the locale by URLs, we will have to generate a URL that contains the locale, resolve the locale in the routes, set the locale, and call the i18n.t method in our views. Another thing which is not immediately visible by the request path alone is that we will want our user to be able to select a locale.

Generate the locale

The following creates a select box to generate our locale. It uses a method that we will create later called url_for_locale which will modify the rails url_for to reload the current page while passing a new locale.


<label><%= t('change_locale') %></label>
<select class='language_switcher'>
  <% I18n.available_locales.each do |locale| %>
    <option
      value='<%= url_for_locale(locale) %>'
      selected='<%= locale == I18n.locale %>'>
      <%= locale %>
    </option>
  <% end %>
</select>

# We use a simple jQuery method to reload the page on click of the locale in the select box.
$('select.language_switcher')
  .change(function(element){
    window.location.href = $(this).val();
});

As mentioned earlier, Rails comes with a method called url_for we are going to wrap this in our new method url_for_locale to redirect to the current page with the new locale.

Scope incoming locale

Your route file is where we are going to scope our locale. If I think about the solution that I really want, it is one where my site has all of the normal URLs that go to the default locale and then any available secondary locales will be visible in the URL.

http://sillypants.com/machin      # default
http://sillypants.com/fr/machin   # french

This seems like it would be 2x the work in the routes file as you would have to re-define the routes but there is really a simple solution. You define your default routes in a method and then use call it directly in the routes file

# route definitions in routes.rb
def site_endpoints
  namespace :admin do
  resources :posts
  resources :images
end

  resources :posts, only: [:index]
end

scope '/(:locale)', constraints: AvailableLocalesConstraint.new do
  site_endpoints
end
site_endpoints

You may have noticed that I am instantiating a classAvailableLocalesConstraint. This is a standard way to scope more complex matching rules for scopes. I don't often need to use something this powerful but here I find it useful to have this level of expression. I am using this because I need something to only match if there is a locale in the params and it is one of the locales I have translations for, otherwise the constraint will fail and the routes file will match further down.

class AvailableLocalesConstraint
  def matches?(request)
    return unless request.params[:locale]

    locale = request.params[:locale].to_sym
    I18n.available_locales.include? locale
  end
end

Set locale based on the params

Now we know that whatever is in the params[:locale] should be a valid locale. Technically, it could also be nil. In order to set i18n.locale we can set a few things in the ApplicationController.

You'll notice that I have also overridden default_url_options, this allows me to reset the locale in all the path_for, url_for calls so that I don't have to specify the locale in things like form submits and any links in the page, either the user has specified a change or it will keep the locale automatically.

before_action :set_locale

def set_locale
  I18n.locale == params[:locale] || I18n.default_locale
end

def default_url_options(options={})
  { locale: I18n.locale == I18n.default_locale ? nil : I18n.locale }
end

Tags: i18n Rails

Control your points of modification 10-22-2017

I was reviewing a controller the other day and I came across a piece of code in rails that modified incoming params in multiple spots. What follows is a contrived example of a solution implemented to handle a date that had to have a different format on the front-end and so had to be parsed according to the user's chosen date format.


class ShoesController < AdminController

    def update
        parse_and_format_date
        if shoe.update(shoe_params)
            redirect_to shoe_show_path
        else
            redirect_to shoe_edit_path
        end        
    end

    def shoe_params
        params.require(:shoe).permit(:buy_date, :title, :id)
    end

    def parse_and_format_date
        params[:shoe][:buy_date] = DateTime.strptime(params[:shoe][:buy_date], user.date_format)
    end
end

The problem I had with this controller is that we are modifying the params in multiple places, first in parse_and_format_dateand then in shoe_params. Also, we aren't particularly clear about it. Without looking into parse_and_format_date it is not immediately clear that it modifies the params.

For me, this is a major no-no but I had trouble articulating why. The only real answer that I could come up with was that debugging later I would have to ask myself where the changes to the params was happening, and the more places I put the changes, the more places I would have to hunt down to ensure that I was not making a bug. Also, parse_and_format_date does not clearly show that it updates the params object. In this file, it's not a big deal, but the bigger the file, the worse it gets, and if you add some concerns the next person to read this code will start scratching their head.

Source of truth

The shoe_params method should appear to be frozen in time. I should not be able to call it in multiple different places in my update method and get a different result. What's more is that the manipulations being done to the params variable should not be so heavy that they can't be done repeatedly if necessary. Also, strong parameters are not usually called multiple times in an action, so it's not crazy to think that it can contain these transforms.

If we made parse_and_format_date idempotent then we could do something like this:

def shoe_params
    params[:shoe][:buy_date] = parse_and_format_date
    params.require(:shoe).permit(:buy_date, :title, :id)
end

def parse_and_format_date
    @parsed_date ||= DateTime.strptime(params[:shoe][:buy_date], user.date_format)
end

In that situation, we would always now what shoe_params contains and it would be clear at any point of any action we call in our controller.

Styling Things in a Component World 03-28-2017

As I slowly work towards using react into some of my projects, my first real question was how to style my components. There have been quite a few evolutions of CSS in the past few years. We've gone from straight CSS to SASS or Less to give better maintainability, Bootstrap to deal with the volitile nature and make our pages a little more standarized. The list goes on but all of these solutions are to make the fundamental problems of CSS less bothersome.

css is awesome

Component centric CSS?

Component centric CSS is the concept of attaching your css to a react component. One of the main benefits that comes from a component driven front-end is the encapsulation that it engenders. No longer does the developer worry about merging multiple small pieces randomly throughout a codebase into a single structure. Instead, each component has its own style attributes. This component has its own error handling, it has its own event listening and it doesn't bother too much with what is going on in other components except when parameters are passed. Each component is the master of its own domain. The main qualm with traditional css is that it is essentially all defined globals. While there have been some attempts to solve this, notably with BEM it feels like a hack to codify your class names to handle a lack of namespacing in CSS.

Applying a component mentality to CSS

I know what you are thinking, "It is called Cascading Style Sheets for a reason". There are a few different approaches available, so bear with me. Here are a few solutions out there.

  • Hard coding: Apply styles directly to elements via the style attribute
  • Styled Components which allows for use of CSS but applied directly to components
  • CSS-IN-JS: which treats your CSS as JavaScript and applies it to components directly.

The Old standard

I am currently using react-bootstrap in my project, and that works exactly how I would expect. There is a defined CSS file included in the site. The react portion handles only the setting of classes and other things which affect the style defined in the included CSS file. The points in using this are:

  • There is potential for clobbering a namespace but the classes are well-defined so it isn't probable
  • Having to debug styles based off of specificity(Why isn't my style showing up?)
  • Having to manage the the structure of the files
  • It is an old evil, but a well-known one. There aren't a lot of surprises in store.

Full disclosure, I am using this as a base and then using CSS-IN-JS to set the rest of my styles.

A New Approach: CSS-IN-JS

Some people have been jumping on the bandwagon for writing inline styles. There is another option though which builds CSS classes dynamically, directly into your components. You may be saying, "Inline Styles?! The warning flags are in the air!", and I will admit that I was skeptical at first. Styles are defined directly on the elements, though they are not truly "inline". This goes counter to everything most of us have learned when getting started with web development. But since, the un-examined belief isn't worth having, lets take a moment to stop and think about why.

Putting CSS Styles directly on elements hurts re-usability.

I want to make styles for a button and be able to use those styles for every instance of said button. The approach to CSS-IN-JS, is to define a dynamic class at instantiation time of a component, from then on, that class is applied to the component. What is nice about this is that you can have multiple styles associated to a component, and then attach them at runtime. You aren't actually re-adding styles to each element.

A side-effect of this, is that you view your styles more as something attached to your components. So structurally it makes sense to keep them with your component. All of my files are located with the component that they style.

  /components
    /MyBadassComponent
      MyBadassComponent.jsx
      styles.jsx

Putting CSS styles directly on elements hurts caching

The styles are defined statically as part of your JavaScript project. So caching them and gzipping them is still part of the deal. The dynamic style building part comes after the page load as part of rendering components. As different components are generated, their styles are dynamically written to a style tag. I suppose that technically your code size doesn't bloat with inline-styles either in using react since the individual components are re-used.

Putting CSS styles directly on elements will essentially override everything else

While this is true for styles written directly to an element via the style attribute, but CSS-IN-JS works by generating classes. This means that if you want to use something like bootstrap, you can happily use their solutions with yours. You can also use other outside libraries and they won't be overridden directly by any styles you choose to use.

Just mix the thing with the thing

Since react is still all new and magical to me, I may do a follow-up article, "Why to never use CSS-IN-JS", it is possible that I will hate it after I've spent some time implementing it. But for now it's my chosen way forward. Here are a few resources for learning more about CSS-IN-JS:

STI Models and a Misconception of DRY 02-25-2017

One of the biggest problems in programming is how to handle and simplify the logic that shows up in your application. Logic which shows up uniformly throughout a class tends to be a smell which indicates the need to represent multiple different concepts. Here is an example of how this can manifest:

Example:

class ThingController < ApplicationController
  def create
    if creation_params[:kind] == 'First'
      First.create(creation_params)
    else
      Second.create(creation_params)
    end
  end

  private

  def creation_params
    params.require(:thing).permit!
  end
end

What's happened here is that we have two separate classes, here First and Second. If you are familiar with STI then you probably have seen this sort of thing often. The problem is that the objects share a data schema, but they will have potentially different views, potentially different validations and they will do potentially different things, ie they have different domains.

Keep it DRY

DRY

People often wrongly cite that they are staying DRY by merging two domains or by combining two functions. But the concept is actually not referring to code. The principal is referring to having a single representation knowledge or a single source. So an example of keeping code dry is to not have a constant show up in all of your view code.

.header
  %p Default circle size is 300 mm.
  .blurb
    Space remaining:
    %span = circle.size - 300

Instead you would store the size as a constant or a method in a class.

class Circle
  def self.max_size
    300
  end
end

.header
  %p= "Default circle size is #{Circle.max_size} mm."
  .blurb
    Space remaining:
    %span= circle.size - Circle.max_size

Manifestation of Excess Logic with STI:

If we look back to our original controller example, we see that there are two separate domains that are being handled by one single controller and that while the total amount of code is less(potentially), we haven't actually simplified our lives. As we add more subclasses to the STI model we will see an unhappy pattern emerge. Potentially we will have a case-statement to select our object and to have them do different things. We will have to define functions like this outside of our models that will then manage the models.

The solution is to not be afraid of having more files, not thinking that less code is necessarily more manageable. Treating the two models as separate resources will make maintenance easier from our routes to our views.

The problem with putting two separate models in the same controller is that there is a branch that starts in the route, and goes all the way to the view. The only argument that I have seen is that you can save on the amount of code you write by putting them in the same controller and giving them the same route. Doing so however makes all of the code associated more complicated as there is now a branch for every reference to the model. If there really is no divergent domain code, then there is no reason for STI. STI is not a way for you to treat two separate things as the same, it is a way for you to treat two things with the same data as different.

Tags: dry STI Rails

Exceptional code 01-22-2017

When I started programming, I never gave much thought to exceptions. I did not realize the benefit. If you write mainly interpreted scripts, they may seem like any other error that explodes during execution. Of course the difference, is that they are controlled explosions.

Some of the primary benefits are that they:

  • Allow you to expect some sort of known potential failure.
  • Allow you to know where the failure came from.
  • Allow you to fail gracefully.

The bad and the ugly

One of the worst things that I've seen is what follows:


def source
  begin
    risky_business
  rescue 
    nil
  end
end

The problem here, is that instead of handling failure, we just ignore it. There is no way to know what happens or why it happens. If risky_business normally returns nil, we may also think that function has passed when it really fails.

The next snippit is better, but still not without its problems.


def source
  raise "The source of all your problems"
end

def bad_exception_catcher
  begin
    source
  rescue Exception => e
    clean_up_the_stuffs
    raise e.message
  end
end

The problem here is a little more subtle. It is clear that we are taking advantage of being able to clean up problem code, however, there is one key problem. We are creating a new exception when we "raise e.message". This means that later in the logs, this call will be the source of the backtrace and not the original source function. If our source function is just one line, then there is no problem, but the more complicated that source function is, the more difficult it will be to pinpoint the problem.

A way to get around this problem, is to just reraise the original exception. In that way we will keep the original backtrace history.


def bad_exception_catcher
  begin
    source
  rescue Exception => e
    clean_up_the_stuffs
    raise e
  end
end

Testing

Typically, exceptions are something that you can and should test for. Also, if you are using ruby and something like rspec, exception testing is supported out of the box.


it "should raise error if user has no email" do
  user = OpenStruct.new(email: nil, name: 'A. Person', uid: 10244201)
  FbGraph2::User.stubs(:me).returns(user)
  expect { user = User.facebook_get_user('access_token') }.to raise_exception(
    LoginException, 'Please use an account with a valid email'
  )
end

In testing for specific exceptions, you can also assure that you don't get unexpected exceptions.