Frosted In

Posted 5 months back at Mike Clark

Frosted In

In Like A Lion

Posted 5 months back at Mike Clark

Who Dat

Dense fog, high winds, cold temps, and big heavy snowflakes. Hello, March 1st.

Episode #444 – February 28th, 2014

Posted 5 months back at Ruby5

ActiveRecord Heatmaps, Atom Editor, Ruby Gotchas and Ruby Tempfiles. Guest hosts Karle Durante and Ken Collins

Listen to this episode on Ruby5

Sponsored by New Relic

New Relic recently posted about Optimizing Your Global Digital Marketing with New Relic
New Relic

Thermometer

The Thermometer gem helps you build heat maps of your activerecord associations
Thermometer

Atom Editor

Github has released the atom editor. A hackable text editor for the 21st Century
Atom Editor

Rails 4.1 starter app with OmniAuth

Daniel Kehoe has released an example application showing how to set up authentication using OmniAuth with Rails 4.1
Rails 4.1 starter app with OmniAuth

Ruby Gotchas that will come back to haunt you

Karol Sarnacki wrote a blog listing popular Ruby gotchas and curiosities that developers should be aware of.
Ruby Gotchas that will come back to haunt you

Make Remote Files Local with Ruby Tempfile

We live in the age of remote resources. It's pretty rare to store uploaded files on the same machine as your server process. File storage these days is almost completely remote Using file storage services like S3 is awesome, but not having your files accessible locally can complicate the performance of file-oriented operations.
Make Remote Files Local with Ruby Tempfile

SICP Wasn’t Written for You

Posted 5 months back at Jake Scruggs

The number of software luminaries who sing the praises of “Structure and Interpretation of Computer Programs” (referred to as SICP) is such a long list that you might think only a crazy person would take issue with it. However, to ignore SICP’s problems and continue to blindly recommend it seems just as crazy.

SICP was the textbook for MIT’s introductory programming class and was a bit of a departure from other into to computer science textbooks at the time.  Wikipedia sums it up nicely:  “Before SICP, the introductory courses were almost always filled with learning the details of some programming language, while SICP focuses on finding general patterns from specific problems and building software tools that embody each pattern.”  Which sounds awesome, but does essentially say that abstract principles will be introduced before the nuts and bolts of a language.  If you think about that for a minute, you may see where the problems will be.

When I was training to be a teacher I took a bunch of education courses.  I got good grades but when I got into the classroom to actually teach I flailed around just trying to keep the class under control and mostly forgot to apply the principles I had learned.  The knowledge was in my head, but it floated, disconnected, from anything in particular.  When I learned these ideas I had no teaching experience, and so, nowhere to place these abstract principles.

SICP’s first chapter explains the basic form of Scheme (a Lisp), some basic operators (+, -, *, /, etc), defining/calling a function, different ways a compiler might evaluate code, and conditionals over the course of a few short pages.  That’s a bit much to swallow all at once, especially the comparative evaluation stuff but that should be easily sorted out with some examples. Right?  Well, that’s not really SICP’s thing. SICP will give you a few trivial examples and then toss you right into the deep end. Then first 2 problems for the reader are pretty easy, but it’s the 3rd that will let you know what yer in for: “Define a procedure that takes three numbers as arguments and returns the sum of the squares of the two larger numbers.” Which seems pretty easy until you realize there are no variables.  You’ll need to figure out an algorithm that can take 3 numbers and, without any intermediate state storage, return the 2 biggest numbers in such a way that you can sum their squares.  I’ll be real honest here, after about 30 min of trying to do this (I have zero functional background so I’m a complete novice here) I gave up and tracked down the answer online.  Of course the answer was simple and concise and made me feel like a chump.  Which is fine, but not really what I was expecting in the first chapter, let alone the 3rd problem of the entire book.

But that’s what SICP is all about -- challenging problems. The rest of the chapter introduces Newton’s method for square/cube roots and lexical scoping just for fun. Chapter 2 is recursion vs iteration in terms of execution speed, resource usage, and transforming from one to the other.  Logarithmic, linear, and exponential growth are dealt with in a few paragraphs and then we’re off to Exponentiation, Greatest Common Divisors, Primality, and implementing Fermat's Little Theorem for probabilistic prime determination. My favorite question from chapter 2 asks the reader to formulate an inductive proof that Fib(n) is the closet integer to ((golden ratio)^n)/5.

Which brings me to another criticism of SICP:  It assumes a familiarity with math that most people just don’t have. A first year MIT student would probably be swimming in math classes so the book assumes that knowledge on the readers part.  Abstract programming principles can be very difficult to find examples for so I’m sympathetic to the plight of the authors, but when you just go straight at math you’re explaining an abstract thing with another abstract thing.

There’s a certain sort of person who gets excited by complicated abstract but internally consistent logic with no real connection to the concrete.  In my experience as a physics teacher, these students do exist but are very rare. Most people need a bit of connection to something tangible in order to have the ideas connect in their brain.

What then is my point about SICP?  Simply that its explanations are overly terse and its problems are large steps past what little is explained.  In light of those things I have recommendations for those who attempt to work through it.

  • If you intend to do every problem, realize that this will take a LONG time and involve a bunch of research.
  • Set a time-box for how long you’re going to spend on a problem before you go look up the answer.  If you’ve spent enough time trying to solve a problem you will still value the answer enough to remember it. 30 min is a good number.  Increase or decrease as your sanity allows.
  • If you feel like something hasn’t been explained:  You’re probably right.  After you find the answer, a close re-reading will reveal a cryptic sentence that you now realize was trying to tell you something. This will infuriate you and is perfectly normal.
  • Work through the book with a group.  This will hopefully allow you to commiserate about how lost you are and get some help.  If there’s someone in there that loves this book and thinks everything is explained perfectly, ignore them.  If they subtly imply that you’re stupid for not getting it:  Leave the group.  You don’t need that static in your life.
  • Do not feel bad about not knowing all this math stuff:  Remember that this book was written for students who would be surrounded by math at the time they read it.
  • Consider learning Lisp before starting this book.  The really important concepts in the book come easier if you’re not also learning Lisp at the same time

Form Filling is Formulaic

Posted 5 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

You probably have more than a few tests that look a bit like this:

fill_in ...
fill_in ...
fill_in ...
fill_in ...
select ...
choose ...
click_on 'Submit'

Filling out a form with Capybara can be very tedious. With Formulaic, we aim to make the process less repetitive and more fun.

fill_form(:user, name: 'Caleb', age: 24, city: 'Boston')
fill_form(:user, FactoryGirl.attributes_for(:user).slice(:name, :age, :city))

Literate Example

# The main entry point for Formulaic is the `fill_form` method.
fill_form(
  # Symbol representing the name of the class the form represents
  :dependent,

  # Pass a hash of attributes to be filled. Works great with
  # `FactoryGirl.attributes_for(:dependent)`.
  {
    # The attribute to set and the value. In this case, Formulaic will
    # `fill_in` the "Name" input with "My dependent".
    name: 'My dependent',

    # If the value of an attribute is a hash, Formulaic will look up
    # translations for the correct model. This is
    # `t('simple_form.labels.profile.zip_code')`.
    profile: { zip_code: '12345' },

    # Works with dates, too!
    date_of_birth: 8.years.ago,

    # When passed an array, it will `check` each of the elements.
    ethnicity: [Profile::ETHNICITY_OPTIONS.first],
  }
)

# Formulaic provides a simple way to look up the translation for the
# submit helper for your model and action. The default is `:create`, so
# you can leave that off.
click_on submit(:dependent, :create)

Formulaic uses I18n conventions to find the text of labels and assumes that you are using SimpleForm.

We hope that you enjoy using Formulaic as much as we do, and as always we encourage you to report any problems you might have and to contribute your improvements!

Redis Scripting with MRuby

Posted 5 months back at Luca Guidi - Home

MRuby is a lightweight Ruby. It was created by Matz with the purpose of having an embeddable version of the language. Even if it just reached the version 1.0, the hype around MRuby wasn’t high. However, there are already projects that are targeting Nginx, Go, iOS, V8, and even Arduino.

The direct competitor in this huge market is Lua: a lightweight scripting language. Since the version 2.6.0 Redis introduced scripting capabilities with Lua.

# redis-cli
> eval "return 5" 0
(integer) 5

Today is the 5th Redis birthday, and I’d like celebrate this event by embedding my favorite language.

Hello, MRuby

MRuby is shipped with an interpreter (mruby) to execute the code via a VM. This usage is equivalent to the well known Ruby interpreter ruby. MRuby can also generate a bytecode from a script, via the mrbc bin.

What’s important for our purpose are the C bindings. Let’s write an Hello World program.

We need a *NIX OS, gcc and bison. I’ve extracted the MRuby code into ~/Code/mruby and built it with make.

#include <mruby.h>
#include <mruby/compile.h>

int main(void) {
  mrb_state *mrb = mrb_open();
  char code[] = "p 'hello world!'";

  mrb_load_string(mrb, code);
  return 0;
}

The compiler needs to know where are the headers and the libs:

gcc -I/Users/luca/Code/mruby/include hello_world.c \
  /Users/luca/Code/mruby/build/host/lib/libmruby.a \
  -lm -o hello_world

This is a really basic example, we don’t have any control on the context where this code is executed. We can parse it and wrap into a Proc.

#include <mruby.h>
#include <mruby/proc.h>

int main(int argc, const char * argv[]) {
  mrb_state *mrb = mrb_open();
  mrbc_context *cxt;
  mrb_value val;
  struct mrb_parser_state *ps;
  struct RProc *proc;

  char code[] = "1 + 1";

  cxt = mrbc_context_new(mrb);
  ps = mrb_parse_string(mrb, code, cxt);
  proc = mrb_generate_code(mrb, ps);
  mrb_pool_close(ps->pool);

  val = mrb_run(mrb, proc, mrb_top_self(mrb));
  mrb_p(mrb, val);

  mrbc_context_free(mrb, cxt);
  return 0;
}

Hello, Redis

As first thing we need to make Redis dependend on MRuby libraries. We extract the language source code under deps/mruby and then we hook inside the deps/Makefile mechanisms:

mruby: .make-prerequisites
       @printf '%b %b\n' $(MAKECOLOR)MAKE$(ENDCOLOR) $(BINCOLOR)$@$(ENDCOLOR)
       cd mruby && $(MAKE)

see the commit

During the startup, Redis initializes its features. We add our own mrScriptingInit(), where we initialize the interpreter and assign to server.mrb.

# src/mruby-scripting.c
void mrScriptingInit(void) {
  mrb_state *mrb = mrb_open();
  server.mrb = mrb;
}

see the commit

Then we can add another command REVAL with the same syntax of EVAL, but in our case MRuby will be in charge of execute it.

# src/redis.c
{"reval",mrEvalCommand,-3,"s",0,zunionInterGetKeys,0,0,0,0,0},

That mrEvalCommand function will be responsible to handle that command. It’s similar to the Hello World above, the only difference is that the code is passed as argument to the redis client (c->argv[1]->ptr).

# src/mruby-scripting.c
void mrEvalCommand(redisClient *c) {
  mrb_state *mrb = server.mrb;

  struct mrb_parser_state *ps;
  struct RProc *proc;
  mrbc_context *cxt;
  mrb_value val;

  cxt = mrbc_context_new(mrb);
  ps = mrb_parse_string(mrb, c->argv[1]->ptr, cxt);
  proc = mrb_generate_code(mrb, ps);
  mrb_pool_close(ps->pool);

  val = mrb_run(mrb, proc, mrb_top_self(mrb));
  mrAddReply(c, mrb, val);

  mrbc_context_free(mrb, cxt);
}

see the commit

Now we can compile the server and start it.

make && src/redis-server

From another shell, start the CLI.

src/redis-cli
> reval "2 + 3" 0
"5"

This was the first part of this implementation. In a future article, I’ll cover how to access Redis data within the MRuby context.

For the time being, feel free to play with my fork.

A GIF is worth a thousand screenshots

Posted 5 months back at opensoul.org - Home

Did you know that GIFs have productive uses? Yep, deal with it! Lately, I have been including GIF screencasts on pull requests that include user interface changes as a way to clearly demonstrate the changes.

It's an extermely effective way to communicate what has changed. These screencasts have other uses, such as showing how to use a feature or demonstrating a bug.

There are a lot of ways to make a GIF screencast, but LICEcap is the best tool I have found found. It is not the prettiest piece of software that I have ever laid eyes on, but it just works and makes fantastic GIFs. The GIF above is 26 seconds long, great quailty, but only 500 KB.

Episode #443 – February 25th, 2014

Posted 5 months back at Ruby5

In this episode we cover new Rubies and rSpec, Ruby’s Demise, AdequateRecord, and a Ruby Heroes reminder.

Listen to this episode on Ruby5

Sponsored by TopRubyJobs

If you're looking for a top Ruby job or for top Ruby talent, then you should check out Top Ruby Jobs. Top Ruby Jobs is a website dedicated to the best jobs available in the Ruby community.
This episode is sponsored by Top Ruby Jobs

RSpec 2.99 and 3.0 beta 2

Late last week Myron Marston and the RSpec team released versions 3.0.0beta2 and 2.99.0.beta2.
RSpec 2.99 and 3.0 beta 2

Ruby is Legal (2.1.1)

Our Ruby is all grown up. Yesterday was ruby's 21st birthday. To celebrate they released version 2.1.1 along with patch releases for 2.0.0 and 1.9.3
Ruby is Legal (2.1.1)

Rumors of Ruby’s Demise

Avdi Grimm wrote a blog post about the 'Rumors of Ruby's Demise' where he talks about the hype around other languages, specially ones with built-in support for concurrency like Erlang or Scala, and how some people in the community see that as sort of a threat to Ruby.
Rumors of Ruby’s Demise

AdequateRecord

Last week Aaron Paterson released a fork of ActiveRecord that can handle twice as many requests per second.
AdequateRecord

Ruby Heroes

Please take a moment to nominate someone that's significantly contributed to our community this past year for a Ruby Hero Award. The awards with be given at RailsConf in Chicago.
Ruby Heroes

Thank You for Listening to Ruby5

Ruby5 is released Tuesday and Friday mornings. To stay informed about and active with this podcast, we encourage you to do one of the following:

Thank You for Listening to Ruby5

EmberJS with a Separate Rails API

Posted 5 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

We just wrapped up a large client project using EmberJS and we learned a few things that are interesting to share.

Ember made this project easier. There are times that a JavaScript framework is unnecessary and there are times that it makes the code much cleaner. This was the latter.

Split Development

We built our API and our JavaScript application as two completely separate applications. We had one repo that held a very basic Rails application with Ember on top and another repo that held the API built in Rails.

Rails instead of Yeoman, Grunt, Brunch, etc

There are a lot of front end development tools that will allow you to build an EmberJS application using CoffeeScript, Sass and the other tools that we like to use on projects. After evaluating them we settled on using a basic Rails application instead; primarily for simplicity. The project had a short timeline and we didn't want to have to worry about another tool that we were not familiar with. In the future I would love to try building an Ember UI using a front end tool such as Tapas with Ember but we didn't have any complaints with using Rails in this case and it made our stack a bit simpler to use.

For Ember in our Rails app we used the ember-rails gem. It provides a basic folder structure for your Ember application inside the app/assets/javascripts directory. The directory structure is similar to a Rails application as you can see below.

controllers/
helpers/
components/
models/
routes/
templates/
templates/components
views/

The one thing that is strange when using the gem for a UI only application is that your app/ directory in Rails is basically unused except for the app/assets/javascripts/ where all the actual work will happen. Another project, EmberAppkitRails, solves this issue by putting the app/ directory into asset pipeline. This is an interesting idea. The gem is pre-1.0 so the API could change.

Ember-rails also provides configuration variables for using the development or production version of Ember depending on your current enviroment. This is nice so that your Ember debug information is automatically removed in production.

Fixtures in Development

To allow rapid development, we built the UI in Ember using only fixtures in Ember Data. This allowed us to very quickly build out complex interactions without having to worry about the API being in place. This was a huge help in moving fast and later we backfilled the API. Being able to change property names without having to worry about migrations or outside API changes was very efficient. An Ember Data fixture is a simple JSON object and you can quickly modify it to your needs. It also handles has many and belongs to references using the IDs of other elements.

App.User.FIXTURES = [
  {
    id: 1
    email: 'user@example.com'
    posts: [1, 3]
  }
  {
    id: 2
    email: 'secondUser@example.com'
    posts: [2,4]
  }
]

App.Post.Fixtures = [
  {
    id: 1
    title: 'The Art of Vim'
    user: 1
  }
  {
    id: 2
    title: '15 Minute Blog in EmberJS'
    user: 2
  }
]

There are downsides to this approach. The first one is the backfill process. We waited too long in the project to connect our API to Ember and ran into issues.

The other problem is that by having the applications in two seperate repos, you can't easily have a full integration test. In order to do this you would need to run both applications on the same machine simultaneously. You would also need some way to make sure that both of the applications were on the same revision for the test.

We decided to test the apps seperately and trust that the API is what we've said it was. This can be frustrating but in our case, it didn't turn out to be a real problem. Once you have wired your API to the UI, you should never change your UI without also changing the API. This was enforced in code review only.

CoffeeScript

I love CoffeeScript and as a company we have embraced it for our all our projects. Ember is no exception to that. CoffeeScript made our Ember application more readable and easier to work with objects. The only thing that is odd is the syntax for a computed property, but that is a minor issue and we quickly adjusted to seeing it as normal.

fullName: (->
  "#{@get('firstName')} #{@get('lastName')}"
).property('firstName', 'lastName')

Fast Tests!

By removing the API from the UI application, we were able to write feature specs entirely in CoffeeScript. This was a huge benefit to the overall success of the project. We could test every interaction in our app precisely and not have to worry about the normal overhead associated with those types of feature specs. The specs only had to deal with JavaScript so it was really fast. A full rake for our UI application was 32.770 seconds including starting the Rails environment. The suite had a total of 71 examples, most of which were feature specs.

Testing in General

We found Ember to be very easy to test in general. Most things break down to Ember.Object and it was easy to grab a controller in a test and verify that a property works as expected. Because we wanted to use Mocha with Chai BDD matchers instead of QUnit, the initial test setup was a bit complex but after using Konacha with a Mocha adapter, it was smooth sailing. The extra setup time for Mocha over QUnit was definitely worth it. The syntax has a much more readable format.

describe 'AggregateStatsController', ->
  describe 'summed properties', ->
    beforeEach ->
      stats = []
      stats.push Ember.Object.create
        clicks: 2
        cost: 1.99
      stats.push Ember.Object.create
        clicks: 4
        cost: 2.00

      model = Ember.Object.create(dailyStats: stats)

      controller = App.__container__.lookup('controller:aggregate_stat')
      controller.set('model', model)

    it 'will sum the number of clicks in the model', ->
      expect(controller.get('clicks')).to.equal(6)

    it 'will sum the cost in the model', ->
      expect(controller.get('cost')).to.equal(3.99)

Feature specs were also very easy to handle. Ember has built in integration test helpers that worked for most of our needs and we used jQuery to augment them in our expectations. The specs were fast enough that we could test small details in the interface that we might otherwise want to omit. Being able to test all the UI interactions gave us a lot of faith in our codebase.

describe 'Navigating SEM Campaigns', ->
  before ->
    App.DailyStat.FIXTURES = [
      {
        id: 1
        clicks: 11
      }
      {
        id: 2
        clicks: 10
      }
    ]

    App.SemCampaign.FIXTURES = [
      {
        id: 1
        name: 'Opening Campaign'
        status: 'active'
        dailystats: [1]
      }
      {
        id: 2
        name: 'Final Sale'
        status: 'active'
        dailyStats: [2]
      }
    ]


it 'shows the daily stats information for campaign', ->
  visit('/').then ->
    clickLink('SEM Campaigns').then ->
      expect(pageTitleText()).to.equal('SEM Campaigns')
      expect(pageHasCampaignWithTitle('Opening Campaign')).to.be.true
      expect(statusFor('Opening Campaign')).to.equal('icon-active')
      expect(clicksFor('Opening Campaign')).to.equal('11')
      expect(pageHasCampaignWithTitle('Final Sale')).to.be.true

Naming your tests

Konacha and Teaspoon both have the downside of not showing a filename when a spec fails. This caused us a lot of pain when we first started so we decided on the convention of using the first describe docstring as the name of the file. In the case above our file would be named navigating_sem_campaigns_spec.js.coffee. This worked out great and made it much easier to find a failing spec.

Overall

Ember is far stabler than I would have imagined given that 1.0 was just released 6 months ago. If you have a project that is highly interactive and requires a lot of data binding, I recommend trying it out. The Ember community has been incredibly helpful on Stack Overflow, their forums and their IRC channel.

Spam improvements

Posted 5 months back at entp hoth blog - Home

Howdy,

Today we deployed a number of improvements to our spam engine. As a result you should see a big decrease of false positives (real discussion incorrectly marked as spam). It is possible that you will also notice a slight increase of false negatives (real spam, not caught). As you continue marking those as spam the situation should rapidly improve.

We also added a new option: you can now ignore spam checking for a particular category. This is useful when you receive emails from an automated source (form, etc), which contains a lot of (sometimes malformed) HTML which may trigger some of our spam rules.

You will find this setting when editing a category:

Don't check for spam

As usual, if you have problems with spam on your site, please contact us. This includes:

  • Emptying a very large spam folder
  • Too many false positives
  • Too many false negatives

Thanks!

Of Late

Posted 5 months back at RailsTips.org - Home

A lot has changed over the years. I now do a lot more than just rails and having railstips as my domain seems to mentally put me in a corner.

As such, I have revived johnnunemaker.com. While I may still post a rails topic here once in a while, I’ll be posting a lot more varied topics over there.

In fact, I just published my first post of any length, titled Analytics at GitHub. Head on over and give it a read.

Introducing Lotus::Controller

Posted 5 months back at Luca Guidi - Home

Lotus development is going well. The experiment of open source a framework per month is sustainable. I have the time to cleanup the code, write a good documentation and deliver great solutions.

This month, I’m proud to announce Lotus::Controller.

It’s a small but powerful and fast framework. It works standalone or with Lotus::Router and it implements the Rack protocol.

Actions

The core of Lotus::Controller are the actions. An action is an HTTP endpoint. This is the biggest difference with other frameworks where they use huge classes as controllers. Think of Rails, where a single controller is responsible of many actions and holds too much informations. Lotus is simple: one class per action.

require 'rubygems'
require 'lotus/controller'

class Show
  include Lotus::Action

  def call(params)
    @article = Article.find params[:id]
  end
end

With this design I wanted to solve a some annoying problems.

An action is an object, whose ownership belongs to its author. She or he, should be free to build their own hierarchy between classes. Lotus offers Ruby modules to be included instead of superclasses to be inherited.

Smaller classes are high cohesive components, where the instance variables have a strong relationship between them. This level of isolation prevents accidental data leaks and less moving parts.

A tiny API of one method makes straightforward the usage of Lotus::Controller. Its argument (params), makes it easy to integrate with existing Rack applications. It returns automatically a serialized Rack response.

A side benefit of this architecture is to take over the control of instantiate an action.

require 'rubygems'
require 'lotus/controller'

class Show
  include Lotus::Action

  def initialize(repository = Article)
    @repository = repository
  end

  def call(params)
    @article = @repository.find params[:id]
  end
end

action   = Show.new(MemoryArticleRepository)
response = action.call({ id: 23 })

assert_equal response[0], 200

In the example above we define Article as the default repository, but during the testing we’re using a stub. In this way we can avoid hairy setup steps for our tests, and avoid to hit the database. Also notice that we’re not simulating HTTP requests, but only calling the method that we want to examine. Imagine how fast can be a unit test like this.

Exposures

Instance variables represent the internal state of an object. From an outside perspective we don’t know which is that state. The simplest and recommended way to get this information is to ask for it. This mechanism is called Encapsulation. It’s one of the pillars of Object Oriented Programming.

The instance variables of an action are necessary for returning the body of an HTTP response. While we’re creating that result from the inside of an action, we can access these informations directly. External objects can retrieve them with getters. These getters are defined with a simple DSL: #expose.

require 'rubygems'
require 'lotus/controller'

class Show
  include Lotus::Action

  expose :article

  def call(params)
    @article = Article.find params[:id]
  end
end

action = Show.new
action.call({ id: 23 })

assert_equal 23, action.article.id

puts action.exposures
  # => { article: <Article:0x007f965c1d0318 @id=23> }

No Rendering, Please

Lotus::Controller helps to build pure HTTP endpoints, rendering belongs to other layers of MVC. It provides a private setter for the body of the response.

require 'rubygems'
require 'lotus/controller'

class Show
  include Lotus::Action

  def call(params)
    self.body = 'Hello, World!'
  end
end

Views and presenters can manipulate the body of the returned response.

require 'rubygems'
require 'lotus/controller'

class Show
  include Lotus::Action

  expose :article

  def call(params)
    @article = Article.find params[:id]
  end
end

action      = Show.new
response    = action.call({ id: 23 })
response[2] = ArticlePresenter.new(action.article).render

Other features

Lotus::Controller offers a set of powerful features: callbacks, automatic management for exceptions and mime types. It also supports redirects, cookies and sessions. They are explained in detail in the README and the API documentation.

Roadmap

On March 23rd I will release Lotus::View.

To stay updated with the latest releases, to receive code examples, implementation details and announcements, please consider to subscribe to the Lotus mailing list.

<link href="//cdn-images.mailchimp.com/embedcode/slim-081711.css" rel="stylesheet" type="text/css"/>

Avoid the Three-state Boolean Problem

Posted 5 months back at GIANT ROBOTS SMASHING INTO OTHER GIANT ROBOTS - Home

Quick, what's wrong with this Rails migration?

add_column :users, :admin, :boolean

Yep - it can be null. Your Boolean column is supposed to be only true or false. But now you're in the madness of three-state Booleans: it can be true, false, or NULL.

Why to avoid NULL in Boolean columns

Boolean logic breaks down when dealing with NULLs. This StackOverflow answer answer goes into detail. For example:

  • true AND NULL is NULL (not false)
  • true AND NULL OR false is NULL

Fortunately, it's easy to fix.

NOT NULL

Adding a NOT NULL constraint means that you'll never wonder whether a NULL value means that the user is not an admin, or whether it was never set. Let's add the constraint:

add_column :users, :admin, :boolean, null: false

But now the migration doesn't run.

Set a default value

The NOT NULL constraint means that this migration will fail if we have existing users, because Postgres doesn't know what to set the column values to other than NULL. We get around this by adding a default value:

add_column :users, :admin, :boolean, null: false, default: false

Now our migration runs, setting all users to be not admins, which is the safest option. Later, we can set specific users to be admins. Now we're safe and our data is normalized.

What's next?

For more on the danger of null values, read If You Gaze Into nil, nil Gazes Also Into You. You can also browse our Postgres-related blog posts.

Episode #442 – February 21st, 2014

Posted 5 months back at Ruby5

We will miss you Jim Weirich.

Listen to this episode on Ruby5

Farewell, Jim.

Posted 5 months back at Phusion Corporate Blog

Today, the sad news has reached us that Jim Weirich has passed away. We’re incredibly sad about this as Jim was one of the nicest people we’ve got to know in the Ruby/Rails community when we first started Phusion. In keeping his memory alive, I’d like to reflect on a particular anecdote that made Jim especially awesome to us and most likely to you as well. I’m sure many of you who were fortunate enough to get to know him can relate to his kindness.

Back in 2008 when Hongli, Tinco and I set out to go to RailsConf to give our very first talk abroad, we met Jim in the lobby of the conference space. We had just attended a talk of his where he had gone through a myriad of valuable do’s and don’ts one should be aware of when giving a talk. These tips proved to be incredibly valuable to us in years to come, and we hope Jim knows how grateful we are for this.

Our talk was scheduled to be held the day after, and seeing Jim’s do’s and don’ts, we were suddenly confronted with how many embarassing “don’ts” we had in our slides. As Jim told the audience that it’s generally a good idea to avoid cliches such as having bulletpoint hell, stock images of “the world” and “business people shaking hands”, we felt more and more uncomfortable. Not only did we have a lot of bulletpoints, we even had an image of “business people shaking hands”… in front of “the world”. We basically tripped over every possible cliche in the book!

But hey, we still had 24 hours, surely we’d be able to fix this up right? Luckily, Jim had the demeanor of a big kind cuddly bear, so we felt compelled to walk up to him after his talk to ask for some help with our slides. Instead of brushing us off, Jim graciously sat down with us for about 2 hours in pointing out the things that could use improvement in the delivery of our talk. And understandibly laughed out loud at our slide with the business people shaking hands in front of the world. ;)

The next day, after giving our talk, we had people walking up to us saying that we killed it. In reality, it was Jim’s tips and kindness in sharing these tips that “killed it”.

We will miss you buddy.

Your friends, Tinco, Hongli and Ninh.