emacs

Emacs is hurting Clojure 

Emacs is a very powerful text editor and its popularity amongst Clojurians is easily understood. Emacs has a long tradition in the Lisp communities as it’s written, in a big part, in a flavor of Lisp called Emacs Lisp.

Because of its history, it handles Lisp code wonderfully, with automatic correct indentation, paraedit, integration with REPLs, etc. But Emacs is really hard to use.

Yeah, most Clojurians know how to use it by now and they suffer from bias: “it’s not that hard” they say. Learning Emacs or Clojure is hard enough. Combining them is insane.

Many Clojurians also say it’s worth it. And again, I think they are biased. Human brains are very good at forgetting pain. Other editors these days are also very powerful and although not as much as Emacs, their usage is intuitive so you can achieve a higher level of proficiency just by using it, without spending time and effort in becoming better at it.

The way Emacs is hurting Clojure is by Clojurians maintaining this myth that you need to use Emacs for Clojure. This is not done by simple statements but by a general culture of jokes saying things such as “you are wrong if you don’t use emacs”.

Me, personally, I don’t care what editor you use. If you want to learn Emacs, go for it. Intellij and Cursive is much easier to use and almost as powerful. When I compare myself to another clojurian, productivity is generally decided by knowledge of the language and libraries, not the editor. If you want to use another editor, so be it. It’s better if they understand Lisp code but it’s not a deal breaker for learning Clojure.

I do care about the success and popularity of Clojure. Coupling the growth of the language to the use of an editor that is hard to use and non intuitive makes no sense. It’s hurting us. Even if you are an Emacs power user, when you talk to a Clojure newbie, please, don’t push it down their throats.

Thank you.

Avoiding threads of emails when developing a Rails application

Call to Buzz, like many applications I developed before, sends emails. Lot’s of emails. To avoid accidentally emailing a customer or random person I use mail_safe. It’s one of the first gems I install on a Rails project and you should too. mail_safe re-writes the to-header so you end up receiving all the emails that you sent.

Once you are receiving all these emails, there’s another problem. They are likely to have exactly the same subject, so, mail clients are likely to group them in threads, which can be annoying. To avoid that, I added this to my ApplicationMailer class and voila! all emails have a unique subject:

if Rails.env.development?
  after_action :uniq_subjects_in_development

  def uniq_subjects_in_development
    mail.subject += " #{SecureRandom.uuid}"
  end
end

Displaying Delayed::Job’s jobs in Active Admin

I’ve been using both Active Admin and Delayed::Job for years now and both have served me very well. It’s very common for me to want to display job records in the admin tool and have some extra tools around them such as:

  • the ability to mark them all for re-run
  • the ability to run one manually (not recommended for production)
  • the ability to run them all manually (also not recommended for production)
  • an easy way to delete them all
  • a good view of the data inside the job

To achieve this, over the years, my admin/delayed_job.rb grew and I took it from project to project. Today I want to share it with you in case you are doing the same:

ActiveAdmin.register Delayed::Job, as: "DelayedJob" do
  collection_action :run_all, method: :post do
    successes, failures = Delayed::Worker.new.work_off
    if failures > 0
      flash[:alert] = "#{failures} failed delayed jobs when running them."
    end
    if successes > 0
      flash[:notice] = "#{successes} delayed jobs run successfully"
    end
    if failures == 0 && successes == 0
      flash[:notice] = "Yawn... no delayed jobs run"
    end
    redirect_to admin_delayed_jobs_url
    I18n.locale = :en # Running delayed jobs can mess up the locale.
  end

  if Rails.env.development?
    collection_action :delete_all, method: :post do
      n = Delayed::Job.delete_all
      redirect_to admin_delayed_jobs_url, notice: "#{n} jobs deleted."
    end
  end

  collection_action :mark_all_for_re_run, method: :post do
    n = Delayed::Job.update_all("run_at = created_at")
    redirect_to admin_delayed_jobs_url, notice: "Marked all jobs (#{n}) for re-running."
  end

  member_action :run, method: :post do
    delayed_job = Delayed::Job.find(params[:id])
    begin
      delayed_job.invoke_job
      delayed_job.destroy
      redirect_to admin_delayed_jobs_url, notice: "1 delayed job run, apparently successfully, but who knows!"
    rescue => e
      redirect_to admin_delayed_jobs_url, alert: "Failed to run a delayed job: #{e.to_s}"
    end
    I18n.locale = :en # Running delayed jobs can mess up the locale.
  end

  action_item do
    links = link_to("Run All Delayed Jobs", run_all_admin_delayed_jobs_url, method: :post)
    links += (" " + link_to("Mark all for re-run", mark_all_for_re_run_admin_delayed_jobs_url, method: :post)).html_safe
    links += (" " + link_to("Delete All Delayed Jobs", delete_all_admin_delayed_jobs_url, method: :post)).html_safe if Rails.env.development?
    links
  end

  index do
    selectable_column
    id_column
    column "P", :priority
    column "A", :attempts
    column("Error", :last_error, sortable: :last_error) { |post| post.last_error.present? ? post.last_error.split("\n").first : "" }
    column(:created_at, sortable: :created_at) { |job| job.created_at.iso8601.gsub("T", " ") }
    column(:run_at, sortable: :run_at) { |post| post.run_at.present? ? post.run_at.iso8601.gsub("T", " ") : nil }
    column :queue
    column("Running", sortable: :locked_at) { |dj| dj.locked_at.present? ? "#{(Time.now - dj.locked_at).round(1)}s by #{dj.locked_by}" : "" }
    actions
  end

  show title: -> (dj) { "Delayed job #{dj.id}" } do |delayed_job|
    panel "Delayed job" do
      attributes_table_for delayed_job do
        row :id
        row :priority
        row :attempts
        row :queue
        row :run_at
        row :locked_at
        row :failed_at
        row :locked_by
        row :created_at
        row :updated_at
      end
    end

    panel "Handler" do
      begin
        pre delayed_job.handler
      rescue => e
        div "Couldn't render handler: #{e.message}"
      end
    end

    panel "Last error" do
      begin
        pre delayed_job.last_error
      rescue => e
        div "Couldn't render last error: #{e.message}"
      end
    end

    active_admin_comments
  end

  form do |f|
    f.inputs("Delayed job") do
      f.input :id, input_html: {readonly: true}
      f.input :priority
      f.input :attempts
      f.input :queue
      f.input :created_at, input_html: {readonly: true}, as: :string
      f.input :updated_at, input_html: {readonly: true}, as: :string
      f.input :run_at, input_html: {readonly: true}, as: :string
      f.input :locked_at, input_html: {readonly: true}, as: :string
      f.input :failed_at, input_html: {readonly: true}, as: :string
      f.input :locked_by, input_html: {readonly: true}
    end

    f.buttons
  end

  controller do
    def update
      @delayed_job = Delayed::Job.find(params[:id])
      @delayed_job.assign_attributes(params[:delayed_job], without_protection: true)
      if @delayed_job.save
        redirect_to admin_delayed_jobs_url, notice: "Delayed job #{@delayed_job} saved successfully"
      else
        render :edit
      end
      I18n.locale = :en # Running delayed jobs can mess up the locale.
    end
  end
end

Nicer warning dialogs with Rails and Bootstrap

Ruby on Rails has a very convenient way of presenting a dialog for potentially dangerous tasks that require some confirmation before proceeding. All you have to do is add

data: {confirm: "Are you sure?"}

A problem with those, though, is that most (all?) browsers make the dialogs quite ugly:

Call to Buzz - ugly dialog

For Call to Buzz, I wanted to finally have something better. Thankfully, there’s a very simple solution, as long as you are using Bootstrap: Twitter::Bootstrap::Rails::Confirm. You just add it to your project and the dialog now looks like this:

Call to Buzz - bootstrap dialog

That looks much better, but it’d be nice if it had a nice title, better matching buttons, etc. It’s easy to do by adding some data attributes to the link and the documentation for this gem recommends creating a new method to use instead of link_to when deleting something. I wasn’t very happy with this approach so I resolved it with pure JavaScript so my links remain oblivious to the fact that I’m using this gem:

$(document).ready(function () {
  $("a[data-confirm]").data({
    "confirm-fade": true,
    "confirm-title": "Call to Buzz"
  });
  $("a[data-method=delete]").data({
    "confirm-title": "Warning",
    "confirm-cancel": "Cancel",
    "confirm-cancel-class": "btn-cancel",
    "confirm-proceed": "Delete",
    "confirm-proceed-class": "btn-danger"
  });
});

And with that, the dialog now looks like this:

Call to Buzz - much better bootstrap dialog

Update: Later on I wanted to be able to define some extra parameters on a link, such as:

data: {confirm: "Are you sure you want to disconnect?", confirm_proceed: "Disconnect"}

To achieve that I re-wrote the code that dynamically adds the extra confirm parameters to look like this (this uses jQuery 3, on earlier version you’d have to do confirm-fade instead of confirmFade):

$("a[data-confirm]").each(function (_, link) {
    var $link = $(link);
    var data = $link.data();
    data = $.extend({}, {
        "confirmFade": true,
        "confirmTitle": "Call to Buzz"
    }, data);
    if ($link.data("method") == "delete") {
        data = $.extend({}, {
            "confirmTitle": "Warning",
            "confirmCancel": "Cancel",
            "confirmCancelClass": "btn-cancel",
            "confirmProceed": "Delete",
            "confirmProceedClass": "btn-danger"
        }, data);

    }
    $link.data(data);
});

Left grouping label with Simple Form and Bootstrap 3

If you are using Simple Form and Bootstrap 3, you probably initialized your app with something similar to:

rails generate simple_form:install --bootstrap

which adds a file called simple_form_bootstrap.rb to your application with many customizations that make Simple Form output nicely formatted Bootstrap 3 forms.

For Call to Buzz, an app I’m building, I had several booleans to display, like this:

Call to Buzz booleans

My problem was that I wanted a label to explain what those booleans are, something like this:

Call to Buzz booleans with label

I achieved that by creating a wrapper that’s a mix between :horizontal_boolean and horizontal_radio_and_checkboxes which I called horizontal_boolean_with_label and looks like this:

config.wrappers :horizontal_boolean_with_label, tag: "div", class: "form-group", error_class: "has-error" do |b|
  b.use :html5
  b.optional :readonly

  b.use :label, class: "col-sm-3 control-label"

  b.wrapper tag: "div", class: "col-sm-9" do |wr|
    wr.wrapper tag: "div", class: "checkbox" do |ba|
      ba.use :label_input
    end

    wr.use :error, wrap_with: {tag: "span", class: "help-block"}
    wr.use :hint, wrap_with: {tag: "p", class: "help-block"}
  end
end
hsbc

Bank says bad debt OK, asset not OK

I want to start buying property with the goal of generating passive income from rent. I’ve read a bunch of books, listen to podcasts, did my research and I stumbled upon a good opportunity that needs more money that I have right now but still a very low amount. So, I need a loan.

I went to a couple of banks to ask for a loan and the answer was essentially: no, we cannot lend you the money to buy this asset that will pay for itself, but if you want to blow it up on a holiday and buy some useless toys, sure, here it is!

Mind you, I can easily pay the loan from my salary. I actually save more money every month than the monthly payment of the loans and I have in the bank a third of the money. My salary has been steadily going up and I’m in an industry in which I’m in a lot of demand. Where my plan is a safe bet, betting on me is even safer.

I’m not one to believe in conspiracy theories but it almost seems like their rules are designed for people to be stupid, instead of smart, with their money; to get in bad debt instead of growing their wealth.

Now, for the nitty gritty details: I asked for a personal loan, some banks disqualify me because you are not allowed to use it for business, some banks disqualify because I’m planning on buying property. They say: “we cannot give you a personal loan for property because you may also get a mortgage”

“Ok, can you give a mortgage then?” “No, because your property is in another country”

“Can you do anything?” “No”

Let’s say I take this supposed mortgage they are so afraid of and the plan fails. Whoever has the mortgage will repossess the property and I’ll pay the bank out of my salary the same way I would if I wanted to spend the money on a caribbean cruise or home improvement.

This feels utterly ridiculous.

Web presence for startups

You build a product, a web or a mobile app and then you need to build a web site to promote it, a.k.a.: the web site. There are several ways of building and maintaining this web site and I have tried most of them and today I have strong opinions about how to do it.

One alternative is to build a custom website as a bunch of HTML and CSS produced by a graphics designer and a coder. Maybe with some server side functionality. If you are building a web app, you might be tempted to mix the web presence with the web app. A lot of tech startups go this route because they have the talent and because it’s the only way to achieve the pristine look that everybody wants and that the industry giants, such as Apple, have.

This is a mistake. The mistake is not considering the process of the evolution of this web site. We only think of the initial task of building it and that tends to be easily achievable, but after that is when the problems really start. Marketing and sales will want constant modifications to that web site both in terms of content and look and feel. They’ll want new landing pages, different kind of analytics. Sometimes they’ll want to scrap the whole thing and start over. This is part of their job and you should just let them do it.

The problem of having the developers of the startup also develop the website is that they need to maintain it and if your marketing/sales people are active enough, they can easily generate enough modifications for a full time person. But your developer needs to be working on the product, not the website. Most changes requested by marketing are going to be relatively small and not as important as improving the product, which means your web presence will be neglected and your marketing person will get annoyed.

The answer is to have CMS and give write access to market and sales. Whether the CMS is WordPress or SquareSpace or something else, it doesn’t matter. I would even recommend to not host it yourself so that the marketing/sales department have a support department that can help them with issues that is not your development team.

This approach will not look as clean, it might feel a bit clunky and people inside and outside the organization are going to constantly fight it. If this is your choice, you’ll have a tough time defending it. I found myself repeating the contents of this blog post to many people over and over again and this is why I’m writing it.