Monthly Archives: June 2015

RSpec let! and before

‘let’ in rspec allows you to define objects and methods to an instance method. Official docs:

Use let to define a memoized helper method. The value will be cached across
multiple calls in the same example but not across examples.

‘let!’ allows you to define an object that is run in a `before` hook. I was curious to the order of execution of ‘before’ hooks and let, so I ran a simple test:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
context 'when testing before' do
  before :all do
    p 'before :all invoked'
  end
 
  before do
    p 'before :each invoked'
  end
 
  let!(:test) { p 'let! invoked' }
 
  it 'prints debug statements' do
  end
end

The results were:

"before :all invoked"
"before :each invoked"
"let! invoked"

So, it seems the before hooks are run BEFORE the let! hooks. This is useful info to note if you need the let! method to be run before the before block, you’ll need to call it manually yourself like the following:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
context 'when testing before' do
  before :all do
    p 'before :all invoked'
  end
 
  before do
    test
    p 'before :each invoked'
  end
 
  let!(:test) { p 'let! invoked' }
 
  it 'prints debug statements' do
  end
end

and we get:

"before :all invoked"
"let! invoked"
"before :each invoked"

Amazon Elastic Beanstalk Hooks

I’ve been working a lot with Amazon Elastic Beanstalk lately to scale our application out. I noticed that there were some nice hooks that elastic beanstalk provides in the /opt/elasticbeanstalk/hooks/ directory. I don’t know why, but Amazon never documented these hooks, but they are very useful to setup your Elastic Beanstalk environment before and/or after your application is deployed. I’ve seen pre-deploy scripts setup additional applications or services on each box (local redis cache service) or a post-deploy script to run a rake task after everything is setup (Did I mention I don’t program in PHP anymore?).

One thing I wish Amazon would do is document and lock down this feature because it is very useful. It seems that Amazon doesn’t really want to do that and the forums warn that it is undocumented and the hooks are subject to change. Well, it is still good to note what order the hooks are fired and what actually triggers them, so here’s my attempt to document all that. You can easily see this in eb log or logging into the server via ssh and checking /var/log/eb-activity.log.

Here are the events that are fired from the AMI (64bit Amazon Linux 2015.03 v1.4.1 running Ruby 2.2 (Puma) ) that I am on for ruby:

Deploy New Instance

1
2
3
4
5
6
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/preinit.
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/pre.
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/enact.
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/post.
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/postinit.
  Successfully execute hooks in directory /opt/elasticbeanstalk/addons/logpublish/hooks/config.

eb deploy

1
2
3
4
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/pre.
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/enact.
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/appdeploy/post.
  Successfully execute hooks in directory /opt/elasticbeanstalk/addons/logpublish/hooks/config.

Reconfigure Scaling

No hooks executed

Changing Environment Properties (eb setenv)

1
2
3
4
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/configdeploy/pre.
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/configdeploy/enact.
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/configdeploy/post.
  Successfully execute hooks in directory /opt/elasticbeanstalk/addons/logpublish/hooks/config.

Restart App Server

1
2
3
4
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/restartappserver/pre.
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/restartappserver/enact.
  Successfully execute hooks in directory /opt/elasticbeanstalk/hooks/restartappserver/post.
  Successfully execute hooks in directory /opt/elasticbeanstalk/addons/logpublish/hooks/config.

Did I miss any event? Please let me know in the comments and I can add it to the list.

If you want your app to deploy with files into these directories, elastic beanstalk provides a way for you to place arbitrary files on the instance and run commands on deploy via the .ebextensions config files. You can check out Danne Manne’s blog on how to do this.

It appears each hook directory is run in sorted order, so if you want something to load up before all the other hooks, prepend it with 01* such as 01script. If you want it run after the other scripts, give it a high number such as 99script.

I’m officially a Ruby On Rails Developer Now

I know I don’t post too much to this blog, but you might start noticing that I have stopped posting PHP and I started to post about Ruby and Rails. Why’s that? Well, it’s because my company has switched over to being a RoR shop. Here’s my short opinion on it…

Ruby and the rails community seem much more mature and bleeding edge. How can I put those 2 together? Well, all the stuff I was working on PHP has been stuff that has strongly been influenced or straight out copied from Rails. I think Rails was one of the most popular MVCs that inspired all of the other ones (and yes, I know there were MVCs before Rails). You see, symfony draws its design off rails.

app/console -> rails/rake
doctrine -> activerecord

As rails has been doing it for much longer (rails is on version 4), it has a much more developed community. I find myself finding more gems and having to write less of my own stuff compared to php. Granted, I still make PRs to the ruby/rails community now.

I’m still getting my head around Ruby as a language, but it does have a much more concise way to write than PHP. Blocks are something that definitely has an advantage over other languages. Yes, you can implement something similar in PHP or other languages with anonymous functions or callbacks, but ruby makes it very natural and intuitive. Overall, after getting over the initial hump of learning a new language, I like it.

One thing that has helped me transition easier is having Jetbrains IDE. I moved straight from PHPStorm to Rubymine and I was very happy that almost 100% of the keybindings that I was used to using in PHP moved right over to Rubymine. The ruby debugger seems actually more flexible than the php debugger as I can actually execute arbitrary code within a breakpoint. This is great for inspecting objects and variables. You could probably do this with PHP, but it just wasn’t as simple.

I look forward to the next languages I’d be learning. So far, going from PHP -> Java -> PHP -> Ruby hasn’t been a bad experience for me. Each time, I learned something new and was able to apply principles from one language in another. I think learning about different languages helps broaden your perspective on design patterns as each language lends themselves to writing code in a certain manner.