Class: GeoModel

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/geo_model.rb

Direct Known Subclasses

SearchModel

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.area_fieldObject



37
38
39
# File 'app/models/geo_model.rb', line 37

def self.area_field
  "ST_Area(#{table_name}.#{geometry_column.name}) AS area"
end

.bbox_filter(params) ⇒ Object

based on mapfish_filter



72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# File 'app/models/geo_model.rb', line 72

def self.bbox_filter(params)
  filter = scoped

  if params['bbox']
    x1, y1, x2, y2 = params['bbox'].split(',').collect(&:to_f)
    box = [[x1, y1], [x2, y2]]
    filter_geom = "'BOX3D(#{box[0].join(" ")},#{box[1].join(" ")})'::box3d"
  elsif params['polygon']
    filter_geom = "ST_GeomFromText('#{params['polygon']}')"
  end

  if filter_geom
    filter = filter.where("ST_Intersects(#{table_name}.#{connection.quote_column_name(geometry_column_name)}, ST_SetSRID(#{filter_geom}, #{srid}))")
  end

  filter
end

.can_edit?(ability) ⇒ Boolean

Returns:

  • (Boolean)


126
127
128
129
130
131
132
133
134
135
136
137
# File 'app/models/geo_model.rb', line 126

def self.can_edit?(ability)
  @@layers ||= Layer.where(:table => self.table_name).all
  can_edit = false
  @@layers.each do |layer|
    # check if any layer with this table is editable
    if ability.can?(:edit, layer)
      can_edit = true
      break
    end
  end
  can_edit
end

.extent_fieldObject



33
34
35
# File 'app/models/geo_model.rb', line 33

def self.extent_field
  "ST_Envelope(#{table_name}.#{geometry_column_name}) AS extent"
end

.forbidden(ability) ⇒ Object



151
152
153
154
155
156
157
158
# File 'app/models/geo_model.rb', line 151

def self.forbidden(ability)
  if ability.nil?
    logger.info "----> Edit access forbidden without login"
  else
    logger.info "----> Edit access forbidden with roles #{ability.roles.collect(&:name).join('+')}!"
  end
  where('1=0') # No access
end

.geo_factoryObject



172
173
174
175
176
177
178
179
180
# File 'app/models/geo_model.rb', line 172

def self.geo_factory
  if self.rgeo_factory_generator == RGeo::ActiveRecord::DEFAULT_FACTORY_GENERATOR
    self.rgeo_factory_generator = RGeo::Geos.factory_generator
    rgeo_factory_settings.set_column_factory(table_name, geometry_column_name,
      RGeo::Cartesian.factory(:srid => 21781, :proj4 => '+proj=somerc +lat_0=46.95240555555556 +lon_0=7.439583333333333 +k_0=1 +x_0=600000 +y_0=200000 +ellps=bessel +towgs84=674.4,15.1,405.3,0,0,0,0 +units=m +no_defs')
    )
  end
  rgeo_factory_for_column(geometry_column_name)
end

.geojson_decode(json) ⇒ Object



90
91
92
# File 'app/models/geo_model.rb', line 90

def self.geojson_decode(json)
  RGeo::GeoJSON.decode(json, :json_parser => :json, :geo_factory => geo_factory)
end

.geometry_columnObject



27
28
29
30
31
# File 'app/models/geo_model.rb', line 27

def self.geometry_column
  col = columns_hash[geometry_column_name]
  col.instance_eval { @srid = srid }
  col
end

.geometry_column_infoObject



8
9
10
11
12
13
# File 'app/models/geo_model.rb', line 8

def self.geometry_column_info
  #spatial_column_info returns key/value list with geometry_column name as key
  #value example: {:srid=>21781, :type=>"MULTIPOLYGON", :dimension=>2, :has_z=>false, :has_m=>false, :name=>"the_geom"}
  #We take the first matching entry
  @geometry_column_info ||= connection.spatial_column_info(table_name).values.first
end

.geometry_column_nameObject



15
16
17
# File 'app/models/geo_model.rb', line 15

def self.geometry_column_name
  geometry_column_info[:name]
end

.geometry_typeObject



19
20
21
# File 'app/models/geo_model.rb', line 19

def self.geometry_type
  geometry_column_info[:type]
end

.identify_filter(searchgeo, radius) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
# File 'app/models/geo_model.rb', line 41

def self.identify_filter(searchgeo, radius)
  if searchgeo[0..3] == "POLY"
    logger.debug "*** POLY-query: #{searchgeo} ***"
    polygon = "ST_GeomFromText('#{searchgeo}', #{srid})"
    scoped.where("ST_DWithin(#{table_name}.#{geometry_column_name}, #{polygon}, #{radius})")
  else
    if searchgeo.split(',').length == 3
      logger.debug "*** CIRCLE-query: #{searchgeo} ***"
      x1, y1, r  = searchgeo.split(',').collect(&:to_f)
      center = "ST_GeomFromText('POINT(#{x1} #{y1})', #{srid})"
      scoped.where("ST_DWithin(#{table_name}.#{geometry_column_name}, #{center}, #{r})")
    else
      logger.debug "*** BBOX-query: #{searchgeo} ***"
      x1, y1, x2, y2 = searchgeo.split(',').collect(&:to_f)
      center = "ST_GeomFromText('POINT(#{x1+(x2-x1)/2} #{y1+(y2-y1)/2})', #{srid})"
      scoped.where("ST_DWithin(#{table_name}.#{geometry_column_name}, #{center}, #{radius})")
    end
  end
end

.sridObject



23
24
25
# File 'app/models/geo_model.rb', line 23

def self.srid
  geometry_column_info[:srid]
end

.user_filter(ability) ⇒ Object

apply user filter for editing Override in descendant classes



141
142
143
144
145
146
147
148
149
# File 'app/models/geo_model.rb', line 141

def self.user_filter(ability)
  if ability.nil?
    forbidden(ability)
  elsif can_edit?(ability)
    scoped #No filter
  else
    forbidden(ability)
  end
end

Instance Method Details

#bboxObject

Custom identify query def self.identify_query(bbox, radius)

scoped.select().where()....

end



66
67
68
69
# File 'app/models/geo_model.rb', line 66

def bbox
  envelope = GeoRuby::SimpleFeatures::Geometry.from_hex_ewkb(extent).envelope #TODO: replace with rgeo
  [envelope.lower_corner.x, envelope.lower_corner.y, envelope.upper_corner.x, envelope.upper_corner.y]
end

#csv_headerObject

header for CSV export



161
162
163
164
# File 'app/models/geo_model.rb', line 161

def csv_header
  #empty by default
  []
end

#csv_rowObject

row values for CSV export



167
168
169
170
# File 'app/models/geo_model.rb', line 167

def csv_row
  #empty by default
  []
end

#modified_by(user) ⇒ Object

update modification attributes (changed_by, etc.) Override in descendant classes



122
123
124
# File 'app/models/geo_model.rb', line 122

def modified_by(user)
  #none by default
end

#to_geojson(options = {}) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'app/models/geo_model.rb', line 94

def to_geojson(options = {})
  only = options.delete(:only)
  geoson = { :type => 'Feature' }
  geoson[:properties] = attributes.delete_if do |name, value|
    # TODO: support for multiple geometry columns
    if name == self.class.geometry_column_name
      geoson[:geometry] = value
      true
    elsif name == self.class.primary_key then
      geoson[:id] = value
      true
    elsif only
      !only.include?(name.to_sym)
    end
  end
  geoson.to_json
end

#update_attributes_from_geojson_feature(feature, user) ⇒ Object



112
113
114
115
116
117
118
# File 'app/models/geo_model.rb', line 112

def update_attributes_from_geojson_feature(feature, user)
  attr = feature.properties
  attr[self.class.geometry_column_name] = feature.geometry
  ok = update_attributes(attr)
  modified_by(user)
  ok
end