The difference between -> and => in CoffeeScript

I had this following code:

@collection.each (post) ->
  $(@el).append @template(post.attributes)
@

I was running in an issue where @el and @template were returning Uncaught TypeError: undefined is not a function. I even created a StackOverflow question about it.

I got the template to render by using jQuery directly like so,

$('#posts').append _template.( $('#home-post-template').html() ).

So this told me that the el or template was not within the scope of the each function. I remembered I was originally referencing one of Buzzstarter’s Backbone files and I had => instead of the -> I had now. Just trying things, I switched out -> for =>. Now it was working. Of course I couldn’t switch it out without understanding why it made a difference. So to the CoffeeScript documentation about the fat-arrow. It basically passes another function passing the outer context of this into an argument. This can be better illustrated with the conversion of CoffeeScript to normal Javascript

Old CoffeeScript

    @collection.each (post) ->
      $(@el).append(@template(post.attributes))
    @

Javascript Equivalent

    this.collection.each(function(post) {
      return $(this.el).append(this.template(post.attributes));
    });
    return this;

New CoffeeScript

    @collection.each (post) =>
      $(@el).append(@template(post.attributes))
    @

Javascript Equivalent

    this.collection.each((function(_this) {
      return function(post) {
        return $(_this.el).append(_this.template(post.attributes));
      };
    })(this));
    return this;

Once I saw the Javascript of the CoffeeScript with =>, it was painfully obvious what I was doing wrong and how => solved the problem. This error was due to my unfamiliarity to CoffeeScript, but Js2Coffee is quite useful in learning the differences.

New Appreciation for Programming

I recently started a new internship at Buzzstarter working with a team of experienced developers. One of the benefits of this internship is to view how good code is written. My first two weeks involved viewing their application’s source code and using similar techniques to build an introduction project.

A specific instance of seeing good code was when I saw a class method called enum.

  def self.enum(options)
    options.each do |attr, values|
      values_method = attr.to_s.pluralize

      class_eval <<-RUBY, __FILE__, __LINE__ + 1
        def self.#{values_method}
          #{values}
        end

        def #{attr}
          self.class.#{values_method}[read_attribute(:#{attr})]
        end

        def #{attr}=(value)
          idx = self.class.#{values_method}.index(value.to_sym)
          raise 'Enum not found' unless idx

          write_attribute(:#{attr}, idx)
        end
      RUBY
    end
  end

The method uses a bit of meta-programming, or at least that’s what I think this is doing, to write attributes to the database. The difference is that the values being written to the database are integer values instead of strings. As it was explained to me, this is a feature MySQL has, but PostgreSQL does not have. This allows for both reading and writing attributes to be quicker. You would then use the the enum method like so.

enum current_status: [:off, :on]

The enum method creates a getter and setter using the attribute current_status with the value being the index of the value within the values array passed in.

There are too many instances already where I’ve read some code and was left smiling about the new technique I just learnt. Not only does viewing the application’s source code show me how good code is written, but making the introduction project has me writing better code.

I am fortunate that I have one of the engineers reviewing my code via code reviews. During these code reviews, Radil, would comment on the specific lines with what I needed to change. I would make the necessary changes until I can create a branch with the feature working, then I would create another pull request. There are about ten parts to the project, but I am still only on the third part. I can already tell there is much more for me to learn.

TinyMCE, ActiveAdmin, and Rails 4

I was installing TinyMCE so I could have a WYSIWYG editor on a textarea within ActiveAdmin when I got the following error.

No route matches [GET] "/assets/tinymce/themes/advanced/theme.js"

I found the similar issue on the tinymce-rails gem’s docs. Losing TINY mce in dev when switching from 3.5.8 to 4.0.2 in Dev

The issue was caused by a change in TinyMCE’s theme. Apparently TinyMCE 4 replaced the ‘advanced’ theme with the ‘modern’ theme. Sure enough when I edited my active_admin.js.coffee CoffeeScript file to:

#= require active_admin/base
#= require tinymce
$(document).ready ->
  tinyMCE.init
    mode: "textareas"
    theme: "modern"
    editor_selector: "tinymce_editor"
  return

That solved the issue I was having. I followed along with this answer on StackOverflow to install tinyMCE to rails.

Railscast 053 Handling Exceptions

GitHub Repo

Heroku App

Rack Middleware

I created this episode in order to understand how rack middleware works. There was really only one line that pertained rack middleware

config.exceptions_app = self.routes

This line is a little hack to define the Rails routes as the rack middleware app that should handle exceptions. From the routes we can then match the status error in a route and map to a controller action.

Route

match '(errors)/:status', to: 'errors#show', constraints: {status: /\d{3}/}, via: :get

This route line provided me with a few lessons. the () in a route is an optional route. A route like products/:id(/:type/:year) would match a route for the product from the id and optional add the type or year params if specified.

The constraints part about further specifies what is acceptable in a route and what is not acceptable. Here we are using regex to constrain the status param to only be 3 digits. This could be useful when getting params from the route. The constraints can be analogous to how validations works for models.

Controller

class ErrorsController < ApplicationController
  def show
    @exception = env["action_dispatch.exception"]
    respond_to do |format|
      format.html { render action: request.path[1..-1] }
      format.json { render json: {status: request.path[1..-1], error: @exception.message} }
    end
  end
end

The @exception instance variable is set to the type of exception raised. The exception is store in the environment’s action_dispatch.exception. The action responds to different formats like html or json. Therequest.pathhas[1..-1]to turn/404to404`

Railscast 052 Update through Checkboxes

The GitHub Repo

The Heroku App

This episode combines the technique shown in Episode 017 habtm checkboxes and Episode 35 Custom REST Actions to update a task’s complete attribute through checkboxes.]

Some of the differences in this episode were the methods used to update the complete attribute. In episode 035, the update_attribute() was used to update a single record. In this episode we used the update_all() method. There was a slight difference in how the update_all() method was used in the video and how it is currently used. In the video the update_all() method accepts two arguments, the attribute with updated value, plus the ids of tasks to be updated. The update_all() method has been changed to accept only one argument, the attribute with the updated value. This creates some problems in specifying which record to update. Luckily, the API for update_all showed the correct way to use the updated version of update_all().

Task.where(id: params[:task_ids]).update_all([“complete=?”, true])

We use the where() method to return tasks fitting the passed in conditional.

The params[:task_ids] were sent from the form within the view.

<%= form_tag complete_tasks_path, method: :put do  %>
  <ul>
    <% @incomplete_tasks.each do |task| %>
    <li>
      <%= check_box_tag "task_ids[]", task.id %>
      <%= task.name %>
    </li>
    <% end %>
  </ul>
  <%= submit_tag "Complete task" %>
<% end %>

Here we use the form_tag because the form is not directly editing attributes on a model. We then specify the path and method to put. I am just realizing this now, but this put should be a patch to match up with what the Rails core team has been doing in transitioning from put to patch to match with RFC’s specifications.

The next part to focus on is the <%= check_box_tag "task_ids[]", task.id %> line. We are creating checkboxes for each task with the value of the task’s id. The name for each checkbox can be specified to task_ids[] because we are using a general check_box_tag. task_ids[] allows the task_ids parameter sent from the form to be an array able to hold multiple records. This is where we get the params[:task_ids] array passed into the where() method.

Which has_many association to use?

Has and Belongs to Many Example Repo

Railscast 047 Two Many-to-Many prompted me to ask this. He showed an has_many_and_belongs_to and an has_many :through example. From what the episode, Ryan Bates seems to generally like has_many :through better because it adds flexibility. What are some of the reasons behind this conclusion?

Differences

The Rails Guides on Associations has a section about this.

For has_and_belongs_to_many the relationship is built through a join table using only two models. A has_many :through relationship creates a third model that belongs_to the two models in the relationship. The circumstances you would want a has_many :through association would be:

if you need validations, callbacks, or extra attributes on the join model.

A case where you might want to have a has_many :through associations would be if you have a feature of ‘following’ within the app. Each user has followers and following users. One relationship could be established, but both do not necessarily have to be established. In the case of followers and following users, you would actually need two relationship tables in the database. ActiveRecord provides the ability to ‘reverse’ a relationship based on what the foreign key is.

There could be a relationships table with follower_id and followed_id. To find a user’s followed users, then you would set the foreign key to the follower_id. To find a user’s followers, then you would set the foreign key to the followed_id and rename this relationship to something like reverse_relationship within the model.

Railscast 046 Catch All Route

The GitHub Repo
The Heroku App

This episode focused on creating a catch all route that redirects to a product’s page based on the partial route typed in. Example: /tele to /television

The routes syntax has been updated since the creation of the episode.

match '*path' => 'your_controller#your_action', via: :get

StackOverflow

You would want to create this catch all route at the bottom of your routes file because it would match all the requests coming into you Rails app otherwise. Because the match all routes redirects to the product page you actually are looking for, this isn’t that bad of an outcome.

After the route catches the input of the user from the route, it then calls the redirect#index. In this controller we can control the behavior of that route.

class RedirectController < ApplicationController
  def index
    if Rails.env.development? || Rails.env.test?
      product = Product.where('name LIKE ?', "#{params[:path].first}%").first
    elsif Rails.env.production?
      product = Product.where('name ILIKE ?', "#{params[:path].first}%").first
    end
    redirect_to product_path(product)
  end
end

In this controller I reused what I learned about PostgreSQL’s LIKE and ILIKE functions from the episode about Simple search forms to separate difference lines of code based on the environment.

There is a single action, index, that is called from the catch all route. We find where the product has a name that is similar to the partial parameter given in the route. We access this partial parameter through the params has with params[:path]. We also call first() to get the first value of the hash. If the user inputed /foo/bar/baz, then it would use the foo value only. Again from episode 037 simple search form, we use the SQL Wildcard % to match anything that starts with the partial route given. If there are multiple records that have the same partial route, then we call first() again at the end of the line to only retrieve the first record.

get '*path' => 'redirect#index'

Railscast 042 With Options

class User < ActiveRecord::Base
  with_options if: :should_validate_password? do |user|
    user.validates_presence_of :password
    user.format_of :password, with: /^[^\s]+$/
  end

  attr_accessor :updating_password

  def should_validate_password?
    updating_password || new_record?
  end
end

class Account < ActiveRecord::Baase
  with_options dependent: :destroy do |acc|
    acc.has_many :customers
    acc.has_many :products
    acc.has_many :invoices
    acc.has_many :expenses
  end
end

This is a convenient method to be aware of. When there are numerous records that have the same options, then using with_options could clean up the code and it more DRY.

The with_options() method accepts the options as the first argument, then it accepts a block for the model class. This argument is the object used to call the validations on. In the case of user, user.validates_presence_of :password does the normal presence validation, but adds the benefit of using the with_options() method.

Further Reading

http://apidock.com/rails/Object/with_options