Add Solr Searching to External Gem and Third Party Database

Problem

Say you have a third party database that you need your rails applications to access. But of course you want it to be modular and use it again for other applications, so you write a gem to provide access to the non-rails standard database. Now you want to add in acts as solr to search across the database from your application.

Solution

Acts as solr is a rails plugin and requires a solr server instance be running and therefore its not necessarily correct to add in the acts_as_solr plugin into your gem library. The consuming applications should be responsible for indexing what they and and how they want it. So a common trick is used to add in the application specific functionality into the gem. Initializers are used to inject the desired functionality into the gems classes. Given you have your gem named third_party_db_gem, create a file in config/initializers named something along the lines of third_party_db_gem_extensions.rb. And put in some code like:

require 'third_party_db_gem'

ThirdPartyModel.class_eval do 
  include ActsAsSolr
  acts_as_solr :fields => [:name, :email, :phone, job]
end

Explanation

So first we had to require our gem, because our gem hasn’t been loaded yet. Then we do a class_eval to inject our solr definition into one of the models. You would repeat that block for every class you wanted to index. Here’s Jay Fields article more on class and instance eval.

Custom Validations for Polymorphic Associatied Models

I recently needed custom validations for a polymorphically associated model, but only for certain polymorphic parents. Lets looks at an example, take the acts_as_addressable plugin, an oldie but a goodie, it lets you attach addresses to all sorts of models. That is a great and extremely useful pattern, I use it all the time. But requirements can’t always stay nice and polymorphic freindly. So we have to know when and how to extend the associations features and when to split the models. But all I needed was different validations for different models, so no need to split. Its simple, just utilize the if option on the validations and the model name stored in the addressable_type column.

SKIP_VALIDATIONS_FOR =['Widget', 'Sprocket']

validates_presence_of :street1, :city, :postal_code, :country, :if=> Proc.new {|obj| !SKIP_VALIDATIONS_FOR.include?(obj.addressable_type)}

This is a pretty simple example, but could easily be expanded to fit different requirements.

Lazer Battles in Nerd World: pew pew pew

For one week, some of the worlds smartest people gather in the desert and its not for a conference. Engineers from all disciplines, artists, craftsmen, writers, thinkers, cat herders and of course pyrotechnicians come to show off their inventions, create art, and to collaborate on a new society; a society based on one nerdy principle: Lazer Battles. Purely metaphorical lazer battles of course, nobody’s actually playing lazer tag, because that would be lame. Its more about who can drag the largest lazer possible to the desert and mount it on top of the largest geodesic dome possible and fire it across the night at other geometric shapes or even other nerds. Those other nerds could possibly be trying to solve a turn based collaborative giant floating Rubik Cube rubik cude or going head to head on a 4 story high Tetris game with player cam. tetris One camp of nerdy rocket surgeons took the fight to the heavens with their Raygun Gothic Rocketship.

Nerdy meets Mad Max and the computer controlled propane cannons were born.

But in Nerd World™, its the giant propane explosion that trumps all others.



(skip to the 1:10 mark for the goods)

I’m not sure what you’ve all heard about Burning Man. But I am hear to let you know that the rumors are true, its more than geek friendly, its built by geeks for geeks. Its not all about being a hippie and dancing the night away, like so many people who haven’t gone think; its about community and collaboration. And if you can only attend one conference next year, it should be in Black Rock City.
black rock city

What the non-tech sector can gain from Agile

Agile/XP methodologies make my job easier and me more productive. There is nothing exclusive about writing software that makes it the only viable profession to apply agile techniques. In the modern business world, the ability to respond to change and communicate effectively is crucial to success. I talk to people outside of software all the time and I hear the same issues over again: problems not getting solved, wrong work being done, meetings ran by power hungry authoritative types talking at you with no real game plan, disjointed teams communicating poorly and outdated work processes can’t get changed. Because of the way software development has evolved over time, we have learned that how you work is just as important as what you are working on and most importantly we actively take steps to improve. So why aren’t more small businesses, non-profits and creative firms having scrums every morning, working in iterations, playing the planning game, utilizing information radiators and honing their processes with retrospectives? The short answer is that they probably are implementing some aspects of Agile, don’t know it yet and could be doing it better.

Baby Steps

If you ever worked or participated in a software team transitioning to Agile, then you know that there is resistance. In a tradition working environment, I could only imagine that were would be even more push back. So if you are reading this and trying to get your non-software team to adopt Agile techniques, move forward slowly and incrementally (just like agile). Here are a few easy things to start trying (one at a time):

  • Get Information Radiator: team chat rooms or wikis
  • Daily Scrum: transparency keeps everybody honest and connected
  • Monthly Retrospectives: low investment cost and high reward

Long Term Goals

Ultimately you would like to be working on a highly functional team, where its harder to be disconnected than in the loop, change occurs easily for the best and no team member can succeed without the whole team succeeding.

In the end, I think that an iterative work structure would be an optimal situation for many jobs, even ones that aren’t producing concrete pieces work with requirements or a definitive end. Thinking, planning and working in 2 – 4 week iterations provide for actual goals to be identified and accomplished. Iterations reduce risk by completing any project in manageable chunks small enough to complete quickly and validate that it’s done right. At the end of these iterations, time is provided and a logical break in the cycle allows for an honest dialogue to occur about how you’re working and what could be improved. Including the stakeholders in retrospectives is useful and sort of like couples counseling. It helps facilitate feedback on the work done to date, how you can improve the perceived value and meet the needs of the client/stakeholder. Here are a few tips for working in iterations:

  • Identify the stakeholders: your boss, client, ceo, investors, board of directors?
  • Communicate with them (at least) every iteration to determine what they need
    • What would provide them the most value right away?
    • Try playing different planning games
  • Iterations don’t have to be concrete or discrete, they can be virtual, so don’t get hung up on that.
  • Demo/show your stakeholder or at least your team what you accomplished.
  • In your retrospective produce actionable/achievable improvement centric goals.

I am a huge proponent of pair programming and feel like there is room for it in the non-software world. Not to say all the work has to be done in pairs. But frequent pairing would cut down on team members working themselves into corners, where they can’t move laterally or vertically because they are the only person who can preform a function. Pairing also leads to better and more communication, which produces empathy and richer interactions between team members.

The overall tenets of Agile are still the same as in the software world; take what you need and leave what you don’t. The key is to:

  • Don’t let your practices slow you down
  • Be agile and not afraid to change
  • Focus on results, communication and constant improvement

If you are a team leader trying to implement Agile in any work environment, software or otherwise, don’t be afraid to reach out for help. There are most likely Agile/Xp user groups in your city and software consultancies, like ELC, willing to help you improve your practices.

Rspec Gotchas and Integration Mode

While trying to spec out a controller with multiple format types, I had trouble getting the right http request invoked. You could always just set the XmlHttpRequest environment variable, but seams hackish to me.
Consider a controller action with multiple request types:

 def update
    respond_to do |format|
      if @object.update_attributes(params[:object])
        flash[:notice] = "Object was successfully updated."
        format.html { redirect_to  object_path @object }
        format.json { render :json => {:flash =>  flash, :object => @object}}
      else
        flash[:error] = @object.errors.full_messages.to_sentence
        format.html { render 'edit' }
        format.json { render :json => {:flash =>  flash, :object => @object }}
      end
    end
  end

With a spec like:

it "should send back json" do
  @controller.should_receive(:render).with({:json => {:flash => {:notice=>"Object was successfully updated."}})
  xhr :put, :update, {:id => "1"}
end

But it will fail to reach the json format block. You could change it to format.js and the test would pass, but the actual functionality would be borked, because its not json. You have to add a format option to the params, then it won’t matter how you make the http request. Both of the below will work, but the later is more correct:

 xhr :put, :update, {:format => "json", :id => "1"}


 put, :update, {:format => "json", :id => "1"}

Moral of the story is that xhr is for js not json. Its easy to forget the small things when you use it everyday.

Rspec Integration Mode

While looking through the rspec-rails rdocs the other day, I discovered integration mode. It puts view specs in your controller specs, so it will act more like Test Unit functional tests. I think it could save time, a lot of lines of setup mocking and yield a wider coverage from each spec. I am not a hardcore view spec’er. I mostly only care that the view doesn’t blow up and I let our Selenium integration tests do the rest. I will be trying out rspec integration mode next week and will make sure to let you know what I think.

Coworking Visas: Offices Without Borders

You_talking

Listen up, Señor T is talking to you. If you have ever tried to spend 8 hours working from a coffee shop, then I don’t have to tell you that it’s not all that it’s cracked up to be. Yes, its a fun dynamic working environment, where people will make you coffee and tasty snacks. However, spotty internet connections, loud music, chatty patrons and lack of power outlets get old quick. But for a cybernomad like me, plopping down a monitor on a desk just isn’t an option.

Shared Workspaces

In recent years, shared community orientated workspaces have been growing in numbers. Places like Souk, which we jokingly refer to as the ELC Portland office, are great places to drop in and work. They have flexible memberships and sport all the accommodations of a regular office (except a boss). I am currently at Office Nomads in Seattle and they even have a kegarator, a 48 inch TV and people doing Yoga.
Officenomads

Coworking Visas

Obama_sez

But you still don’t want to be stuck in the same city in the same shared office, because a shared office is still an office. Enter the Coworking Visa, which is a network of shared workspaces like Souk and Office Nomads that allow you to float between them if you have a membership at one location. This isn’t a small network either. They are in most major and some not so major US cities and 13 countries around the world, including Buenos Aires where I spent the last month. Anyways, its totally amazing and I encourage you all to pick up your computer and wander with it. Sorry the pictures are so bad, I broke my camera.

Egginhole

Yes that is egg-in-a-pancake-hole, I had it for breakfast.