The goal of my project is to create a Ruby on Rails backend API application for my Bachelor’s thesis RubyMotion mobile application. In this post I will focus on the following topics:

  • Seeding the production database
  • User registeration / authentication
  • Creating the Tasks for users
  • Sending the reminders as e-mails and push notifications
  • Polishing for real production use (logging, monitoring, bundle installing “the right way”)

Seeding the production database

The whole application and the database is designed so that we are going to have a lot of ready, system-provided data on the appliances and the task_templates tables. You could say this data almost makes up half of the whole product: it’s useless to have a system to manage your home maintenance tasks, if you have to come up with the appliances, tasks and their intervals yourself and enter everything into the system by hand. You could as well just use a spreadsheet or any reminder application for that.

The obvious way might be insterting that data manually to the production database, either with a graphical database tool like Sequel or just by giving SQL commands. But at least right now I’d rather manage the data straight withing the source code repository (and have the data kept safe that way) than manage any SQL backups and such things. Ruby on Rails provides a clean way of seeding the data to any environment with seeds.rb.

To create a sample set of data I just had to put this into db/seeds.rb:

bed = Appliance.create!(name: 'Bed', description: 'Bed is something you sleep in')
  TaskTemplate.create!(appliance_id: bed.id, name: 'Turning the mattresses', description: 'Mattresses have to be turned every 4 months in order to remain in good condition.', instruction: 'Take the mattress, flip it over.', interval: '90')

dishwasher = Appliance.create!(name: 'Dishwasher', description: 'Dishwasher washes your dishes')
  TaskTemplate.create!(appliance_id: dishwasher.id, name: 'Clean the filters', description: 'There will be garbage on the filters, for you\'re machine to work properly, you have to clean it every two weeks', instruction: 'Take out filter, wash by hand, put back filter.', interval: '14')
  TaskTemplate.create!(appliance_id: dishwasher.id, name: 'Add salt', description: 'If you live in an area where the water is hard, you have to add some salt as softener. Adding the salt will make your dishes crystal clear when the come out.', instruction: 'Put salt somewhere.', interval: '30')

fire_alarm = Appliance.create!(name: 'Fire alarm', description: 'It will save your life just hanging on the ceiling')
  TaskTemplate.create!(appliance_id: fire_alarm.id, name: 'Checking the battery', description: 'According to XYZ you have to check the batteries every month.', instruction: 'Push the battery check button and wait for sound. Release button. Change battery if there is no sound.', interval: '30')
  TaskTemplate.create!(appliance_id: fire_alarm.id, name: 'Replacing your fire alarms', description: 'According to XYZ, you have to completely replace your old fire alarms every 10 years.', instruction: 'Out with the old, in with the new', interval: '3600')

And then run the task bundle exec rake db:seed to create the entries into database (in development). For production, I’m going to run the same command with RAILS_ENV=production.

One caveat with this approach is, if I accidentally run the same rake task db:seed again, I will create these entries again and have duplicate data. So when I add one more appliance or task_template, I have to do it somehow else.

Sources: The Rails 4 Way book, chapter 6.4 Database Seeding

Creating the Tasks for users

Creating with a simple rake task. It even works!

desc "Creates all the tasks that are due, to be sent out later"
task create_tasks: [:environment] do
  users = User.all

  users.each do |user|
    puts "Creating tasks for #{user.email}"
    user.possessions.each do |possession|
      appliance = possession.appliance
      puts "Creating tasks for appliance #{appliance.name}"
      appliance.task_templates.each do |template|

        next if Task.where({template_id: template.id}).any? { |t| t.still_valid?(template.interval) }

        puts "Creating a new task: #{template.name}"
        new_task              = Task.new
        new_task.name         = template.name
        new_task.description  = template.description
        new_task.instruction  = template.instruction
        new_task.interval     = template.interval
        new_task.template_id  = template.id
        new_task.status       = "created"

        begin
          possession.tasks << new_task
          new_task.save
          puts "New task saved to database"
        rescue
          puts "Error saving #{new_task}"
        end

      end
    end
  end
end

Sending the reminders as e-mails and push notifications

Got it working using Sendgrid

Polishing for real production use (logging, monitoring, bundle installing “the right way”)

WIP