Thursday, February 19, 2015

RGeo Problem on Production Environment

BIP Informed Partnership Project is a national project that aims to decrease winter mortality of managed honeybee colonies by helping beekeepers keep colonies alive through surveys and data collection. Beekeepers can register a hive, assign it to a scale and track daily cycles such as weight, humidity and temperature. Over time, the data collected on the new Web application will become a research tool for scientists to use to discover patterns that could shed some light on this significant problem.
As a very basic use case, we needed to implement a feature for creating a Bee Hive. Here is the scenario:
  1. The beekeeper logs in.
  2. He adds the information for his hive.
  3. Using Google Maps API, he chooses the hive location on a map.
  4. He saves the newly created hive.
  5. On the next page he sees his hive information in addition to a Google Map Marker pinned to the hive location on a map.
To facilitate implementing mentioned scenario we used RGeo Gem which is a Geospatial data library for Ruby. Using RGeo we are able to work with Geospatial objects directly from our Ruby models. Further, using activerecord-postgis-adapter gem we can save our geospatial objects in PostgreSQL using PostGIS addon. The process is pretty straightforward.
Basically, in our hive model we use:
class Hive < ActiveRecord::Base
    set_rgeo_factory_for_column(:current_location, 
                              RGeo::Geographic.spherical_factory(:srid => 4326))
    ...
end
This defines current_location attribute on Hive model as a spherical object. Spherical objects have latitudes and longitude accessors.
Then in our location creator, we have the following code:
require_relative "./coordinate_builder"
require 'rgeo'

class LocationCreator
  DEFAULT = "default"

  def self.create(lat_lng)
    return nil if lat_lng == DEFAULT

    lng, lat = CoordinateBuilder.parse(lat_lng)
    geographic_factory = RGeo::Geographic.spherical_factory
    geographic_factory.point(lng, lat)
  end
end
LocationCreator receives an string which is comprised of latitude and longitude and then it tries to create a spherical object. Later during hive creation, we assigned the return value of 'create' method to @hive.current_location:
def create
    Hive.transaction do
      @hive = Hive.new(hive_params)
      @hive.current_location = LocationCreator.create(params[:hive][:latlng])
      respond_to_create
    end
end
Later in the views, we use the following piece of code to fetch the latitude and longitude of the points in order to create a Google Maps marker for the hive and pin it on a map:
<% if @hive.current_location.present? %>
  var myLatlng = new google.maps.LatLng(<%= @hive.current_location.latitude %>, <%=@hive.current_location.longitude %>);
  var mapOptions = {
    zoom: 16,
    center: myLatlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP
  }
<% end  %>
We implemented the feature. Everyone was happy. The code was working on production and development environments. Our test was passing flawlessly on the development system. Also, the feature worked perfectly on every production server. Later we decided to host our project on Heroku. Here was when the problem with RGeo Objects started.
On Heroku, initially we used good naive Webrick which comes as the default web server. But Webrick is not scalable. For the sake of scalability, we considered switching our production server to Puma.
When switched to Puma, calling @hive.current_location.lon and @hive.current_location.lat in my Javascript views throws the error:
ActionView::Template::Error (undefined method 'lon' and 'lat' for #<RGeo::Cartesian::PointImpl:0x007f700846c970>)
Meanwhile, we tried to access the current_location latitude and longitude via heroku run rails console. The interesting thing was that fetching lat and long values on Heroku console returns correct values that we expected which meant that objects are correctly saved in the database. So the problem should be on the presentation side.

Workaround:  I don't know exactly why in the Javascript codes the SphericalPointImpl converts to Cartesian::PointImpl. we changed the javascript calls in the views from @hive.current_location.lat to @hive.current_location.y. Also for latitude, we did the same: @hive.current_location.lon to @hive.current_location.x.
due to the fact that RGeo::Cartesian::PointImpl supports .y and .x methods and not .latitude and .longitude methods.
This fixed the problem for us. So if you ran into this problem don't forget to check method availability on your objects.

Saturday, July 28, 2012

Working with Oracle's geometry column directly from active record

On the company, we develop with Ruby on Rails framework. We create GIS web applications, awesome applications well indeed ;) . Due to some integration and standard issue, three years ago, company migrated from PostgreSQL to Oracle Database.

PostgreSQL has a brilliant support in Rails community and there are excellent integration with geometry types, too; but Oracle's support isn't very promising.
In company, we repeatedly need to create geometry objects and store them in database. It was so easy in PostgreSQL with help of PostGIS addon; the Postgres' active record adapter did it like a charm. We could manage to create and save our geometry objects like this:
It was completely easy, we worked with our geometry object like any other objects with no exception. The problem aroused, when we moved to Oracle. (Trust me, It was not my choice at all ;) )

There is no support for geometry types in oracle enhanced adapter; the adapter needed to communicate with an Oracle database; so for every query involved with Geometry types, we directly connected to database and executed raw SQL to retrieve, insert or update data.

It was a pain in the neck. Sometimes, the queries were extremely lengthy. We wanted our former approach. we desired to easily interact with active_record and create and save objects directly without any raw SQL.

The question was how?

There was an spatial adapter which could handle creating oracle tables with geometry columns through rails migrations. I used it, it helped me a great deal in managing geometry types from migrations.
But, directly persistence of objects was still indefeasible. I forked default oracle enhanced adapter for active record and hacked it until I found out how to handle the situation.
The result gem is now available in github. you can use it in your rails program to directly save your ruby objects involving Oracle's SDO_Geometry types to Oracle DB.
Instead of including default oracle enhanced adapter in your Gemfile, you can include my forked version.

The process is described in this stackoverflow thread.

I hope it helps you all in handling Oracle geometry types directly from active record.

Tuesday, June 28, 2011

The path toward craftmanship

Recently, I read Andy Hunt's Refactor Your Thinking, one of the best non technical books I've read in the recent months. The book emphasize Dreyfus's learning model. The root of this model backs on 1970's. Hubert and Stuart Dreyfus began doing researches on how people attain and master skills. According to this model, a person when attaining a skill will go through five different stages: Novice, Advanced Beginners, Competent, Proficient and finally Expert. The model is a skill-based model, It emphasize on the learning process of a person for each skill versus the learning process of a person totally. This model has a great impact on agile methodologies. It was interesting for me, according to model, most of the people in their life are in novices and advanced beginners stages. They would not be expert at all.
They will not be watchful in what they will learn. They only try to solve a problem which occurred for them for the sake of solving, not learning. This is the problem. For being a craftsman or an expert, we must go through these stages, one by one, step by step.
All is this, this model describes the path which a novice must go to become a journeyman and then, undergo finally toward craftsmanship. I delighted a lot with reading this book and acquainting that the Dreyfus model is existed. Read It, You'll get benefits of it in long-term.

Sunday, June 12, 2011

Daily issues

Finally the end semester's exam have been arrived, and the first of them, Software Engineering II passed today. I hope the others of them, including numerical computations, Artificial Intelligence and finally Web Engineering arrive sooner and pass greatly. Every year, In every semester I try to bear in my mind that it will be great if I try a little harder across the semester against exam's night waking sessions. :) but it won't happen in these four years. This semester will be one of my lasts in the university and probably Iran, hope to these other exams finish sooner and of course with good results. This post hasn't any specific purpose, It was a honest confession about the future and my own mental thoughts.
About my reading favourites, I'm waiting for Uncle Bob's "clean coder" impatiently and I'm reading Steve Freeman's "Growing Object Oriented Software, Guided By Tests" currently. It's a wonderful and high content book and is recommended by biggest lords of the industry.
Today, Is June 12th and in persian calendar Khordad 22th. The anniversary of fraud in Iran presidential election in 2009 that caused great pain in the country. Anti-Government activists called a rally for today. We will see what will happen. Hope that the government change his behavior and do not treat with his people with brutality. AMIN, However I'm agnostic ;)
Ok, enough. I try to write review for Freeman's awesome book after completing reading of it.

Friday, March 11, 2011

How to read a paper?

Today, I read a paper about "How to read a paper". What a recursive sentence ;) .It's worse to have a glance on it. . The idea is formed in a three-pass approach. The first pass is to have an abstract view and a bird's eye view of the paper. The view will have more details in second pass and have the lowest abstraction in the last one. Let me brief. Here is the paper, This disciplined approach prevents us from drowning in the details before getting a bird's-eye-view.

Wednesday, March 9, 2011

HTTP POST & GET Requests

Very short post, Developers, please, for the sake of god, DO NOT use hyperlinks for an action which supposed to change the state of anything on the server, they're to be used only to fetch information. Hyperlinks generate an HTTP GET request and are not appropriate for this situation.
Here’s the issue. Almost since HTTP was invented, it has been recognized that there is a fundamental difference between HTTP GET and HTTP POST requests. Tim Berners-Lee wrote about it back in 1996. Use GET requests to retrieve information from the server, and use POST requests to request a change of state on the server.
For example in Rails development, instead of using link_to helper, we must use button_to, It generates an HTML form that contains just a single button. When the user clicks the button, an HTTP POST request is generated and a POST request is just the ticket when we want to do something like add an item to a cart.
So, Please, Please DO NOT misuse hyperlinks for the wrong action.

Sunday, February 6, 2011

Chad Fowler's Passionate Programmer - A Guide Toward Masterdom

After reading Dave Thomas's "The Pragmatic Programmer" which was one of the best books I ever read until this day, recently I read Chad Fowler's "The Passionate Programmer". It was wonderful. It guided me through a deep journey toward success in my career.

It doesn't depend on what career you have. I, as a software developer enjoyed from the book, as equal as my sister which is an Architect. She said me that, the book was perfect and she's using its tips and hints in the company for achieving the best performance and above all for getting the joy.

During reading book I write its interesting notes. Below are the important ones.

1. Learn more about business, financial issues and money.
2. Join an open source project and try to contribute.
3. Learn about internals of Java Virtual Machine and class loading.
4. Read the book ten-day MBA to better understand how a business operates.
5. Teach one topic you know well.
6. Learn each week one aspect of Java you haven't explore yet.
7. Read code.
8. Maintain a todo list. Have a log about your daily progress.
9. 8 hours work scheme seems awesome! Never work more than 8 hours a day from now on.
10. Maintain a log about your commitments and review them. What is your hit-rate of success?
11. Invest more on your social skills. Context and perception matters. So find out who you are dealing with and answer accordingly.
12. Invest more in your English, writing abilities and generally clear communication.
13. The path is the end! Read more about mindfulness and the Buddhism philosophy!
14. Having a road map for your product is what keeps you moving forward.
15. Make your improvements small and incremental but daily.
16. For most of the big, difficult goals you’re striving for, it’s important to think not about getting closer each day to the goal as it is to think about doing better in your efforts toward that goal than yesterday.
17. Avoid waterfall career planning, Set big goals, but make constant corrections along the way. Learn from the experience, and change the goals as you go ultimately.
18. Carve out weekly time to investigate the bleeding edge.make room for at least two hours per week in order to research new technologies and to start to develop skills in them.build simple apps with them. understand what new technology enable us to do in order to current-techs.
19. best ways for showing yourself is public speaking and publishing, Start from web: First, read blogs. second open your own blog.
20. if you have no deadline, you will not finish the work.
These were most important notes.
I strongly recommend you to read the book, It's the key toward the success and above all, the key toward to feeling of joy in your life.
"But I say to you that when you work you fulfill a part of earth’s furthest dream, assigned to you when that dream was born, and in keeping yourself with labour,
you are in truth loving life, and to love life through labour is to be intimate with life's inmost secret.
Kahlil Gibran, The Prophet