#ruby, #rails, #OOP, #javascript, #ember

12/20/16

Cacheing Ruby With APICache gem

If you're running a rails app then chances are you're playing with multiple apis. This week I found myself working with the robust JIRA api so that I could return worklogs and do something meaningful (and more user friendly) for a client.

You could easily write your own cacheing class using timestamps and urls as keys for the queries, but I really like this gem (APICache by Martyn Loughran) because it has a couple nice features out of the box like :period, :valid, and :cache timeout options. The gem is also simple; it consists of two main classes, Api and Cache, which are both under 100 lines of code. The other few classes are wrappers that help you configure your 'mem-cache' store which we'll get into later.

First download the api_cache gem Then add 'config/initializers/api_cache.rb' And add this code
if Rails.env.production?
  APICache.store = APICache::DalliStore.new
end
This will set up a dalli store (which is a pure Ruby client for accessing memcached servers) when you are in production and will use memory to cache data when running locally. This allows you to boot up your app and play around without having to run a second server every time. When you get ready to deploy to production read the Dalli docs to learn more about how the process works.

In my example we are retrieving large data sets. Returning the JSON and refreshing the page took around 15 seconds, no bueno. In order to cache all our request to the Jira server we used our own wrapper class that defined a 'get' method. This class inherited from our jira::client so that way all gets would go through our logic. If we want to implement a new http request (like put, patch, post) we can follow the same pattern. We then wrapped our get method with APIcache logic
  def get( url )
    APICache.get(url, :cache => cache_timeout, :timeout => 15) do
      super(url)
    end
  end

  def cache_timeout
    skip_cache ? 1 : 3000
  end
The skip_cache is an attr_accessor which we pass in when we instantiate this class on specific situations. Besides that we use our default cacheing timeout setting which is 50 mins.
The Api Cache gem also allows these configurations 
{
  :cache => 600,    # 10 minutes  After this time fetch new data
  :valid => 86400,  # 1 day       Maximum time to use old data
                    #             :forever is a valid option
  :period => 60,    # 1 minute    Maximum frequency to call API
  :timeout => 5     # 5 seconds   API response timeout
  :fail =>          # Value returned instead of exception on failure
}
Check out api_cache gem for the official docs.

11/23/16

That's not broken... Re-think your design

It has been 9 months since I have posted on this blog and I have learned a TON in that amount of time. I'm restarting this blog to share some a few things I learn each month. To start off, here's some Devise.

We have all used the very popular Rails engine ‘Devise.’ A couple weeks ago I came across a new use case with the gem about overriding one of their standard methods. I was dealing with the mailer and a client wanted to redirect to a new page after a user confirmed their account via email. Simple enough. The problem was my agency uses a custom rails engine that preinstalls Devise and therefore some of it's initial configuration; like overriding the 'after_confirmation_path' method.

First I tried overriding Devise's method just like their docs suggest, but that didn't work for some reason. Maybe I source the gem from my local (instead of rubygems.com) and update its child method 'after_confirmation_path' to fit my needs? That could work if I was doing some serious customization to the overall gem, but I clearly was not. I also tried setting the Devise mailer to use my own mailer in its configuration. No luck.

Then I considered calling the 'grandparent' (which would be the devise method) and overriding it for the project I was in. Apparently this is a thing, but there was no way that it felt right for doing something so simple. This was my first hint that I was on the wrong track. (stack overflow dealing with grandparent override). I also tried setting our custom gem's mailer to use my own mailer in its configuration. No luck.

In the end, the solution was a simple configuration that I had overlooked. I'm currently learning Ember.js and I stumbled upon this quote the other day that relates to my problem here: "It sounds like right now you're working hard to do something that Ember deliberately discourages. Generally I find when I'm fighting the framework it's because my understanding of the problem is different (and often not as complete as the framework authors)."
Devise.setup do |config|
  config.mailer = 'UsersMailer'
end

The lesson here: Pay attention to signs that you are on the wrong path and moving too quickly. When solving simple problems look for simple solutions. Don't reinvent the wheel. I should have spent more time looking at my first solution instead of dismissing it and thinking there was something wrong with my apps design, or Devise.

Here's the end product, which Devise easily points to in their docs
class Users::ConfirmationsController < Devise::ConfirmationsController

  protected

  def after_confirmation_path_for( resource_name, resource )
    super + "?email=#{params[:email]}"
  end

end

2/17/16

Hired

Yesterday I accepted my first job with a small start up out of Jacksonville Beach working in Ruby on Rails. Looking back at this blog I can't help but feel proud of how far I have come. From start to finish it took me six months to land an entry level position, which is what I hoped for in the beginning but had no idea if it was possible for me.

I'm going to shut down this blog/project, and start focusing on new things. I will be looking for more ways to blog and contribute to coding communities as this has been a lot of fun tracking my progress.

-John

1/27/16

Hackathon, Meetups and More

I have been in Orlando the fast couple weeks, here's an update of whats been going on.

Tabs on Tallahassee Hackathon
- this was my first all-day hackathon and I had a great experience. Not knowing what to expect, I showed up in the morning and joined a team. We were given some basic guidelines (which can be found on the link above), put into a room for about nine hours, and asked to come up with something. Two guys on my team held senior positions and took the lead. We decided to use Angular (something I had not used before) and began working on our idea which gave information on your legislator by zip-code, then according to your own political beliefs, compared your representative to a legislator that lined up with your own political view points.
Tabs on Tally Hackathon

We did not get to finish our app but our code is on my github. I contributed to our front end but also spent time watching the back end of our app development, I was very interested in watching the pros thought process. Overall this was a great experience working with a team and I look forward to more events like this.

Ruby Jax Action Cable - my favorite meetup that I attend, this one was back in Jax Beach. Best thing was more reassurance that testing is the path to getting hired. During this meetup Eric Bundy gave a talk and did some live coding on Rails 5 new Action Cable feature.

Jax Tech Meet Up - another cool meetup back in Jax Beach, this one was really great for networking and I received some new contacts that I hope will lead to some freelance work.

WordPress Site Optimization - meetup in downtown Orlando at Envy Labs, pretty cool introduction to wordpress and another great networking experience.
Meetup @ Envy Labs Orlando

 
I also volunteered to give the next talk at Ruby Jax in a couple of weeks. My topic is REST and how it makes Rails awesome.

-John

1/13/16

Resume, LinkedIn, Portfolio and Updates from this Week

Past few days I have been all over rubymonk.org, Lynda.com, guides.rubyonrails.org, Rails 4 Way (3rd edition) and some treehouse videos. I also have a portfolio page up here, updated resume, and linkedin ready to go.

I never considered myself to have attention deficit disorder until I began to learn to code, not because I constantly struggle with looking at my phone or scrolling my FB feed, but because of the sheer amount of things I want to learn it's hard to decide where to focus my attention. I have decided I am going to finish the month of January out strong and begin seriously looking for work in February. In the mean time I am continuing to practice ruby, study rails, read everything I can, and see if I can find some freelance or open source projects that I can contribute to.
White Board | Check List | Recent Goals

Here a summary of the past few days:

Ruby Monk-- Finished ruby primer and am 2 1/2 chapter into Ruby Primer Ascent. I have found this site very helpful with brushing up on things I have forgotten and also teaching me a lot of new things about the way Ruby works. New things I have learned include: converting implicit blocks to explicit, how a class instance variable can be beneficial, the difference between puts and p, and how to use the splat method.

lynda-- finished RSpec course and have a good grasp on how the framework works and why it is so important. Learned how to write model specs (usually the most important specs), helpers, controllers with the HTTP requests, and views.

RubyonRails Guides and Rails 4 Way-- I have spent a few hours today reading over how routes work and was amazed at how it really cleared up a lot for me. Even though I have been feeling good about rails this was super helpful to be reminded about HTTP and route names and how 'resources :name' works.

Tree House-- signed up for a trial (I know, getting spread thin) but am really interested on their take on how ActiveRecord works. I am currently finishing up their Database Foundations tutorial working with sqlite and Work Bench.

When I first decided to learn to code I was attracted by the lucrative salaries and job security. That part of the industry seems less important to me the more I learn. In the past five months I have developed a different way of interpreting things and that is really rewarding. It's amazing because I have been putting in long hours (10-12 hours a day the past 8 days) and am genuinely enjoying the process. My focus is on being a great programmer and I have never felt better.

-John

1/9/16

Great expect(ations) w RSpec

The holidays are over an I have been chipping away daily. This week I have dedicated much of my time to learning RSpec and testing ruby frameworks. Searching around there isnt an abundance of testing information for beginners on the web, but I signed up for a free trial at Lynda.com and have been very happy with there 6hr class on testing with RSpec. I'm about 3/4 finished and have learned much of the syntax and theory behind RSpec.

If your learning Rails you should learning some sort of testing. It may not be necessary in the beginning, but you will need to have it in your tool belt when things get a bit more complex. Also, I feel that if you wait too long to learn testing it could become a bottle neck in your growing progress.

Also, I can't recommend Lynda.com enough. I have only viewed their course on testing ruby frameworks but I have a feeling that everything they do is at a high level. I plan to continue to use them as I move forward.

Here is a summary of what I have learned the past two days with Lynda and RSpec:

The hiearchy is important: spec file => example groupe => nested group => example => expectations is really the meat of the whole operation and once I understood that I really started to understand the big picture.

Helper methods: It is important to keep your suite as fast as possible therefore encouraging frequent tests. Now this is a non issue for small projects, but as things grow I could see how this would slow things up. Helper methods help keep unnecessary tests from running and slowing down the process.

The let method is really cool because it creates a helper method that takes one argument, which is the name of the method you want to create and then a block of code.

ex.
let(:car) { Car.new}

it "allows reading for :wheels" do
  expect(car.wheels).to eq(4)
end

you can also use subject as your helper

ex.
subject {Car.new}
  it ....
end

........and going farther you can define subjects implicitly by using a class name as the 'describe' argument

ex.
(this is how it looked like before)
describe 'Car'
  subject { Car.new }
  it ....
  end
end

*is the same thing as

describe Car
    it...
    end
end

^Here the subject is implicitly defined. As soon as it encounters the class as an argument it creates a helper method with the subject as the class Car. this works well if the subject you are working with is in only one class.

For Rails testing I learned about SHARED EXAMPLES, which is where RSpec begins to get more complex.

Shared examples let you describe behaviour of classes or modules. When declared,
a shared group's content is stored. It is only realized in the context of
another example group, which provides any context the shared group needs to
run.

In rails this comes in handy when describing things like 'CRUD' in your controller.

ex.
describe ProductsController do
  describe '#index'
    it_behaves_like 'a standard index action'
  end
  describe '#new'
    it_behaves_like 'a standard index action'
  end
end

.....and so on

Should be finishing up the rest of the course tomorrow along with the last touches on my portfolio and resume. I'll be going to a meetup this next Thursday at Hashrocket in Jax Beach, and they give opportunities at the end for attendees to put projects up in front of the group to have it "torn a apart" by the pros. I hope to have a TDD or BDD app built from the ground up by then; I'd love to get live feedback that way.

it is now 4 a.m., please excuse the typos

-John