cityway-transdev/activeroad

View on GitHub
app/models/active_road/street_number.rb

Summary

Maintainability
A
0 mins
Test Coverage
module ActiveRoad
  class StreetNumber < ActiveRoad::Base
    serialize :tags, ActiveRecord::Coders::Hstore
    attr_accessible :objectid, :tags, :number, :geometry, :physical_road_id, :location_on_road

    validates_uniqueness_of :objectid
    validates_presence_of :number, :stored_geometry

    belongs_to :physical_road, :class_name => "ActiveRoad::PhysicalRoad"
    def road
      @road or physical_road
    end
    def road=(road)
      @road ||= road
    end

    before_validation :compute_locate_on_road, :on => :create

    def stored_geometry
      read_attribute :geometry
    end

    def geometry
      stored_geometry or computed_geometry
    end

    def computed_geometry
      road.at estimated_location_on_road
    end

    def location_on_road
      stored_location_on_road or estimated_location_on_road
    end

    def stored_location_on_road
      read_attribute :location_on_road
    end

    def compute_locate_on_road
      if stored_location_on_road.nil? and stored_geometry 
        self.location_on_road = road.geometry.locate_point(stored_geometry) 
      end
    end

    # TODO rename into estimated_location_on_road
    def estimated_location_on_road
      if previous and self.next
        number_ratio = (number.to_i - previous.number.to_i) / (self.next.number.to_i - previous.number.to_i).to_f
        previous.location_on_road + number_ratio * (self.next.location_on_road - previous.location_on_road)
      end
    end

    def previous
      @previous ||= road.numbers.find :first, :conditions => ["number < ?", number], :limit => 1, :order => "number desc"
    end

    def next
      @next ||= road.numbers.find :first, :conditions => ["number > ?", number], :limit => 1, :order => "number"
    end

    def number
      Number.new read_attribute(:number)
    end

    class Number < String

      alias_method :numeric_value, :to_i

      def suffix
        gsub(/^[0-9]+/,'')
      end

      def +(value)
        self.class.new "#{numeric_value+value}#{suffix}"
      end

      def -(value)
        self.class.new "#{numeric_value-value}#{suffix}"
      end

    end

  end
end