Tag: Ruby on Rails

  • This is an update of an old post of similar name but for a newer version of Devise and with better design decisions. The old post was for Devise 1.0.8, this one covers 4.0.0

    I was trying to have a single page with both sign in and sign up forms with Devise 4.0.0 but this applies to whenever you want to show log in or registering individually or together anywhere on your site other than the views and controllers Devise creates for you.

    For my task, I created a custom controller for it with a single new action as the create actions would be in the respective already existing Devise controllers. Something like this:

    class Users::SessionsOrRegistrationsController < ApplicationController
      def new
      end
    end

    And then I created a new.html.erb (actually, new.html.haml, but I digress) that contained both log in and sign up one after the other. Something like this:

    <h2>Sign up</h2>
    
    <%= form_for(resource, as: resource_name, url: registration_path(resource_name)) do |f| %>
      <%= devise_error_messages! %>
    
      <div class="field">
        <%= f.label :email %>
        <%= f.email_field :email, autofocus: true %>
      </div>
    
      <div class="field">
        <%= f.label :password %>
        <% if @minimum_password_length %>
          <em>(<%= @minimum_password_length %> characters minimum)</em>
        <% end %>
        <%= f.password_field :password, autocomplete: "off" %>
      </div>
    
      <div class="field">
        <%= f.label :password_confirmation %>
        <%= f.password_field :password_confirmation, autocomplete: "off" %>
      </div>
    
      <div class="actions">
        <%= f.submit "Sign up" %>
      </div>
    <% end %>
    
    <hr/>
    
    <h2>Log in</h2>
    
    <%= form_for(resource, as: resource_name, url: session_path(resource_name)) do |f| %>
      <div class="field">
        <%= f.label :email %>
        <%= f.email_field :email, autofocus: true %>
      </div>
    
      <div class="field">
        <%= f.label :password %>
        <%= f.password_field :password, autocomplete: "off" %>
      </div>
    
      <% if devise_mapping.rememberable? %>
        <div class="field">
          <%= f.check_box :remember_me %>
          <%= f.label :remember_me %>
        </div>
      <% end %>
    
      <div class="actions">
        <%= f.submit "Log in" %>
      </div>
    <% end %>

    I actually ended up creating two _form partials and including them. In either case, when you try to render those views, you’ll get errors about some missing methods. You need to provide those as helper methods so my controller actually looks like this:

    class Users::SessionsOrRegistrationsController < ApplicationController
      def new
      end
    
      private
    
      def resource_name
        :user
      end
      helper_method :resource_name
    
      def resource
        @resource ||= User.new
      end
      helper_method :resource
    
      def devise_mapping
        @devise_mapping ||= Devise.mappings[:user]
      end
      helper_method :devise_mapping
    
      def resource_class
        User
      end
      helper_method :resource_class
    end

    And now it works.

  • There’s a gem called bundler-audit that checks whether any of the gems in your project have open security advisors against them. A year or so ago there was an infamous month in which Rails itself got three of those. It was terrible and I think bundler-audit is a good idea. My only problem with it is having to remember to run it: it just won’t happen. I need to run it automatically and an easy way to do that is to run it as part of my tests.

    Unfortunately, bundler-audit doesn’t make it easy. It’s designed for the command line and that’s it, but these days it’s easier than a year ago and I recommend everybody to add them to their integration tests. Here’s how we do it at Watu:

    require "test_helper"
    require "bundler/audit/database"
    require "bundler/audit/scanner"
    
    class SecurityTest < ActionDispatch::IntegrationTest
      should "not have any vulnerable gems" do
        Bundler::Audit::Database.update!
        scanner = Bundler::Audit::Scanner.new
        scanner.scan do
          raise "There are vulnerable gems in your Gemfile. Run bundle-audit check to know more"
        end
      end
    end
    

    I don’t try to show the vulnerable gems because I found those methods to not be easily reusable and I didn’t want to copy them because they look like they might change at any moment. It’s not a big problem, if something is wrong, you should run bundle-audit check anyway.

  • Most applications, web, desktop or mobile, handle some kind of data. When we are developing them we generally generate some sample data to play with and we forget to ever run the application without it. The problem is that the first impression people will get of our app is without data. And first impressions are important.

    In the application I’m building, Watu, we are resorting to just create some sample data for customers to play with. Making the application beautiful and meaningful without data is just too hard. It seems the guys at JetBrains spent some time thinking of this because RubyMine 4.0 shows this when there are no open files:

    I think that simple change it’s a good step towards making the application nicer in the no-data scenario, making people happier, as well as making people more productive in it, making the application more useful.

    I do wonder why they didn’t include the most useful of the shortcuts: ⌘⇧N. I think I press that more than any other. It pops up this little dialog:

    in which you can type and it’ll search among all your files (and files inside the gems, that is, libraries, of your project if it doesn’t match anything in your project or if you enable by ticking the include non-project files):

    What I really like, compared to other implementations of this feature, is that you can add more parts of the path, for example:

    Without that feature, my productivity would drop a 10%. I’m not exaggerating, that’s my estimation, as I recently have to code using TextMate instead of RubyMine.

    Before you send me the hate-mail, I know TextMate has a similar feature although I think not as advanced (not without plugins at least) but since the key shortcut was different, it was almost like it didn’t exist for me, so I experienced coding without that feature at all.

    Another potentially useful way to find code is to use ⌘N which allows you to search for a class:

    But since in a Rails projects most classes are in a file with the same name (but underscore instead of camel case) and the file dialog allows me to find views, wich the class dialog doesn’t, I never use the class dialog.

    No… I’m not affiliated with JetBrains, makers of RubyMine in any way. I just love the tool and I wish more Ruby programmers would give it a try because I think they’ll also find it useful and the more people that are using it, the more resources JetBrains is likely to put into its development which ultimately benefits me. And they are cool guys, a pleasure to deal with every time I report a bug or ask for a feature.

  • I find myself needing to have the full URLs in Rails’ logs. Normally you get something like:

    [sourcecode lang=”text”]
    Started GET "/" for 127.0.0.1 at 2011-08-27 13:13:10 +0200
    [/sourcecode]

    but I needed

    [sourcecode lang=”text”]
    Started GET "http://foo.bar:3000/&quot; for 127.0.0.1 at 2011-08-27 13:13:10 +0200
    [/sourcecode]

    because the app does different things depending on the domain and when it fails, I have to know which URL was hit. The solution I ended up with was adding this in an initializer:

    [sourcecode lang=”ruby”]
    class Rails::Rack::Logger << ActiveSupport::LogSubscriber
    protected

    def before_dispatch(env)
    request = ActionDispatch::Request.new(env)
    info "\n\nStarted #{request.request_method} \"#{request.url}\" for #{request.ip} at #{Time.now.to_default_s}"
    end
    end
    [/sourcecode]

    That’s monkey-patching Rails’ own logger. Credit for the solution goes to numbers1311407.

    My question for the people using Rails, do you think having a configurable logger in Rails would be useful or nice? If so, I could make a patch for Rails but I have made patches before that failed to gather the needed popularity and thus were ignored. I’m not wasting my time like that again.

  • A recent update to RubyGems is causing a lot of deprecation warnings like these:

    [sourcecode]
    NOTE: Gem::Specification#default_executable= is deprecated with no replacement. It will be removed on or after 2011-10-01.
    Gem::Specification#default_executable= called from /usr/lib/ruby/gems/1.8/specifications/rubygems-update-1.4.1.gemspec:11.
    NOTE: Gem::Specification#default_executable= is deprecated with no replacement. It will be removed on or after 2011-10-01.
    Gem::Specification#default_executable= called from /usr/lib/ruby/gems/1.8/specifications/bundler-1.0.7.gemspec:10.
    NOTE: Gem::Specification#default_executable= is deprecated with no replacement. It will be removed on or after 2011-10-01.
    Gem::Specification#default_executable= called from /usr/lib/ruby/gems/1.8/specifications/file-tail-1.0.5.gemspec:10.
    [/sourcecode]

    I generally like software to move forward and the way to do that is deprecate and then after a while, make backwards incompatible changes. It’s painful but there’s no other way.

    I do have a problem with all the cron jobs of my web apps like Keep on Posting or DNSk9 flooding my inbox with those warnings. Thankfully, that’s not hard to fix. Where I was doing:

    [sourcecode lang=”bash”]
    rake pre_calculate_thingies > /dev/null
    [/sourcecode]

    now I’ll be doing:

    [sourcecode lang=”bash”]
    rake pre_calculate_thingies 2>&1 >/dev/null | grep -v default_executable
    [/sourcecode]

  • When you are building systems like my Keep on Posting or my DNSk9 that send emails there’s always the danger that you’ll accidentally fire emails from your development machine to real users. You really don’t want to do that because it’s annoying and extremely unprofessional.

    It happened to me a couple of times. Thankfully, nothing serious. But I learned the lesson. That’s why in my user models now I have a safe_email method which I use instead of accessing email whenever I’m about to actually deliver a message.

    The method safe_email ensures that nobody will receive a message unless I’m in production and at the same time it’s good for testing. Obviously most of the time in development and testing mode I don’t deliver emails at all, but sometimes, I make an exception:

    def safe_email
      if Rails.env.production? || email.blank? # If the email is blank (or nil), let it be.
        email
      else
        "pupeno+#{email.gsub("@", "_AT_")}@pupeno.com"
      end
    end
    
  • When I need to run something periodically on production, I always implement it as a rake tasks and install it as a cron job. Nevertheless there’s some setup to do in the task to have proper logging and error reporting.

    This is the template I use for creating those tasks:

    namespace :projectx do
      desc "Do something"
      task :something => :environment do
        if Rails.env.development?
          # Log to stdout.
          logger = Logger.new(STDOUT)
          logger.level = Logger::INFO # DEBUG to see queries
          ActiveRecord::Base.logger = logger
          ActionMailer::Base.logger = logger
          ActionController::Base.logger = logger
        else
          logger = ActiveRecord::Base.logger
        end
    
        begin
          logger.info "Doing something"
        rescue Exception => e
          HoptoadNotifier.notify(e)
          raise e
        end
      end
    end

    While in development mode, it outputs to the console for convenience.

  • For a personal project I’m working on, I need to find out the smallest time period with more than 5 records. I essentially wrote this code:

    period = [1.week, 1.month, 1.year].select_first do |period|
      Record.where("published_at >= ?", period.ago).count >= 5
    end
    

    only to find out that the select_first method doesn’t exist. So I wrote it:

    module Enumerable
      def select_first(&predicate)
        self.each do |item|
          if yield(item)
            return item
          end
        end
        return nil
      end
    end
    

    and then of course, I tested it:

    require "test_helper"
    
    require "enumerable_extensions"
    
    class EnumerableTest  2 }
      end
    
      should "select_first the first one" do
        assert_equal 1, [1, 2, 3, 4].select_first { |i| i >= 1 }
      end
    
      should "select_first the last one" do
        assert_equal 4, [1, 2, 3, 4].select_first { |i| i >= 4 }
      end
    
      should "select_first none" do
        assert_equal nil, [1, 2, 3, 4].select_first { |i| i >= 100 }
      end
    end
    
  • There are thousands of books that will take you from illiterate to novice in any programming language. But finding those that will take you from novice or intermediate to expert is hard. I remember reading Effective Java some years ago and wishing I had something like that for Python. I’ve never found one.

    Metaprogramming Ruby is a great book full of very interesting knowledge, full of those things that separate a Ruby programmer and an export Ruby programmer. Before finishing the book I’ve already put to use some of the lessons and it saved me a lot of time. The book payed for itself before I’ve finished reading and I really recommend it to anyone who is serious about coding in Ruby.