active_map 0.12.2 → 0.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +13 -7
- data/lib/active_map/version.rb +1 -1
- data/lib/generators/active_map/install/install_generator.rb +32 -5
- data/lib/generators/active_map/install/templates/enable_postgis.rb.tt +5 -0
- data/lib/generators/active_map/mappable/mappable_generator.rb +90 -0
- data/lib/generators/active_map/mappable/templates/add_geometry_column.rb.tt +6 -0
- data/lib/generators/active_map/mappable/templates/model.rb.tt +3 -0
- data/llms.txt +3 -4
- metadata +5 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9de22853c093f901edd0cdce8369b569ef2c84997e846a05fe33b51a4dbed1b3
|
|
4
|
+
data.tar.gz: e1d5d728d054a275a65e195a487fa89b937dbe88d544606884c7db30bfec1076
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 58df67bdcf82aa7fef438e3ef10a190b38156ddd664605dbf45eab2cee23cd6f4a5b379242387723431220a1b9320ca1b6cad7740d25220615f4e54083b216fb
|
|
7
|
+
data.tar.gz: 85054688467ed05e7e2a1b4c2a8c4baad09136a37b0b2583edd939ead8583a34148e24d66e93849c41c663c2ef8c3af78ad562b4ea37f945fbd7f408e3ba955f
|
data/README.md
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# ActiveMap
|
|
2
2
|
|
|
3
|
+
[](https://rubygems.org/gems/active_map)
|
|
3
4
|
[](https://github.com/itisbryan/active_map/actions/workflows/ci.yml)
|
|
4
5
|
|
|
5
6
|
Declarative maps for Rails + PostgreSQL/PostGIS. A Ruby DSL turns your models
|
|
@@ -21,18 +22,23 @@ gem "active_map"
|
|
|
21
22
|
|
|
22
23
|
```bash
|
|
23
24
|
bundle install
|
|
24
|
-
bin/rails g active_map:install # mounts
|
|
25
|
+
bin/rails g active_map:install # mounts /maps, initializer + sample map, PostGIS migration, Stimulus wiring
|
|
26
|
+
bin/rails db:migrate # enables the postgis extension
|
|
25
27
|
```
|
|
26
28
|
|
|
27
|
-
|
|
29
|
+
Make a model mappable — the generator adds the geometry column (with a GiST
|
|
30
|
+
index) and `acts_as_mappable` in one step:
|
|
28
31
|
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
```bash
|
|
33
|
+
bin/rails g active_map:mappable Warehouse coordinates:point
|
|
34
|
+
bin/rails g active_map:mappable DeliveryZone area:polygon
|
|
35
|
+
bin/rails g active_map:mappable Route path:line
|
|
36
|
+
bin/rails db:migrate
|
|
34
37
|
```
|
|
35
38
|
|
|
39
|
+
Both generators are idempotent — safe to re-run. Prefer to wire it by hand?
|
|
40
|
+
See the Model DSL below.
|
|
41
|
+
|
|
36
42
|
## Model DSL
|
|
37
43
|
|
|
38
44
|
```ruby
|
data/lib/active_map/version.rb
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
+
require "rails/generators"
|
|
2
|
+
require "rails/generators/migration"
|
|
3
|
+
require "rails/generators/active_record"
|
|
4
|
+
|
|
1
5
|
module ActiveMap
|
|
2
6
|
module Generators
|
|
3
7
|
# Idempotent: safe to re-run; every step checks for prior installation.
|
|
4
8
|
class InstallGenerator < Rails::Generators::Base
|
|
9
|
+
include Rails::Generators::Migration
|
|
10
|
+
|
|
5
11
|
source_root File.expand_path("templates", __dir__)
|
|
6
12
|
|
|
7
13
|
MOUNT = 'mount ActiveMap::Engine, at: "/maps"'.freeze
|
|
@@ -12,12 +18,24 @@ module ActiveMap
|
|
|
12
18
|
application.register("active-map", ActiveMapController)
|
|
13
19
|
JS
|
|
14
20
|
|
|
21
|
+
def self.next_migration_number(dir)
|
|
22
|
+
ActiveRecord::Generators::Base.next_migration_number(dir)
|
|
23
|
+
end
|
|
24
|
+
|
|
15
25
|
def mount_engine
|
|
16
26
|
return say_status :skip, "route (already mounted)", :yellow if routes_file.include?("ActiveMap::Engine")
|
|
17
27
|
|
|
18
28
|
route MOUNT
|
|
19
29
|
end
|
|
20
30
|
|
|
31
|
+
def create_postgis_migration
|
|
32
|
+
if postgis_migration_exists?
|
|
33
|
+
say_status :skip, "PostGIS migration (already present)", :yellow
|
|
34
|
+
else
|
|
35
|
+
migration_template "enable_postgis.rb.tt", "db/migrate/enable_postgis.rb"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
21
39
|
def create_initializer
|
|
22
40
|
template "initializer.rb", "config/initializers/active_map.rb", skip: true
|
|
23
41
|
end
|
|
@@ -48,17 +66,26 @@ module ActiveMap
|
|
|
48
66
|
def next_steps
|
|
49
67
|
say <<~MSG, :green
|
|
50
68
|
ActiveMap installed. Next steps:
|
|
51
|
-
1.
|
|
52
|
-
2.
|
|
53
|
-
|
|
54
|
-
3.
|
|
55
|
-
4. Define layers in app/maps/sample_map.rb, then render with <%= active_map :sample %>.
|
|
69
|
+
1. Run migrations: bin/rails db:migrate (enables PostGIS)
|
|
70
|
+
2. Make a model mappable, e.g.:
|
|
71
|
+
bin/rails g active_map:mappable Warehouse coordinates:point
|
|
72
|
+
3. Define layers in app/maps/sample_map.rb, then render with <%= active_map :sample %>.
|
|
56
73
|
Docs: README.md and llms.txt in the gem root (`bundle show active_map`).
|
|
57
74
|
MSG
|
|
58
75
|
end
|
|
59
76
|
|
|
60
77
|
private
|
|
61
78
|
|
|
79
|
+
def migration_version
|
|
80
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def postgis_migration_exists?
|
|
84
|
+
Dir.glob(destination.join("db/migrate/*.rb")).any? do |f|
|
|
85
|
+
File.read(f).include?('enable_extension "postgis"')
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
62
89
|
def destination
|
|
63
90
|
Pathname(destination_root)
|
|
64
91
|
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
require "rails/generators"
|
|
2
|
+
require "rails/generators/migration"
|
|
3
|
+
require "rails/generators/active_record"
|
|
4
|
+
|
|
5
|
+
module ActiveMap
|
|
6
|
+
module Generators
|
|
7
|
+
# Scaffolds a mappable model in one step:
|
|
8
|
+
#
|
|
9
|
+
# rails g active_map:mappable Warehouse coordinates:point
|
|
10
|
+
# rails g active_map:mappable DeliveryZone area:polygon
|
|
11
|
+
#
|
|
12
|
+
# Adds a geometry column migration (with a GiST index) and injects
|
|
13
|
+
# `acts_as_mappable` into the model (creating it if absent). Idempotent.
|
|
14
|
+
class MappableGenerator < Rails::Generators::NamedBase
|
|
15
|
+
include Rails::Generators::Migration
|
|
16
|
+
|
|
17
|
+
source_root File.expand_path("templates", __dir__)
|
|
18
|
+
|
|
19
|
+
GEOMETRY_TYPES = {"point" => "Point", "polygon" => "Polygon", "line" => "LineString"}.freeze
|
|
20
|
+
|
|
21
|
+
argument :geometry, type: :string, default: "coordinates:point",
|
|
22
|
+
banner: "column:point|polygon|line",
|
|
23
|
+
desc: "geometry column and shape, e.g. coordinates:point"
|
|
24
|
+
|
|
25
|
+
def self.next_migration_number(dir)
|
|
26
|
+
ActiveRecord::Generators::Base.next_migration_number(dir)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def validate!
|
|
30
|
+
return if GEOMETRY_TYPES.key?(shape)
|
|
31
|
+
|
|
32
|
+
raise Thor::Error, "unknown geometry type #{shape.inspect} (one of: #{GEOMETRY_TYPES.keys.join(", ")})"
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def create_geometry_migration
|
|
36
|
+
if column_migration_exists?
|
|
37
|
+
say_status :skip, "column migration (already present)", :yellow
|
|
38
|
+
else
|
|
39
|
+
migration_template "add_geometry_column.rb.tt",
|
|
40
|
+
"db/migrate/add_#{column}_to_#{table_name}.rb"
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def add_acts_as_mappable
|
|
45
|
+
path = File.join(destination_root, "app/models", "#{file_path}.rb")
|
|
46
|
+
declaration = " acts_as_mappable geometry: :#{column}, type: :#{shape}\n"
|
|
47
|
+
|
|
48
|
+
if File.exist?(path)
|
|
49
|
+
if File.read(path).include?("acts_as_mappable")
|
|
50
|
+
say_status :skip, "acts_as_mappable (already declared)", :yellow
|
|
51
|
+
else
|
|
52
|
+
inject_into_class path, class_name, declaration
|
|
53
|
+
end
|
|
54
|
+
else
|
|
55
|
+
template "model.rb.tt", "app/models/#{file_path}.rb"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def done
|
|
60
|
+
say_status :info,
|
|
61
|
+
"Run bin/rails db:migrate, then add a layer: " \
|
|
62
|
+
"layer :#{table_name}, #{class_name}.all", :green
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def column
|
|
68
|
+
@column ||= geometry.split(":").first
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def shape
|
|
72
|
+
@shape ||= geometry.split(":")[1] || "point"
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def geometry_type
|
|
76
|
+
GEOMETRY_TYPES.fetch(shape)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def migration_version
|
|
80
|
+
"[#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}]"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def column_migration_exists?
|
|
84
|
+
Dir.glob(File.join(destination_root, "db/migrate/*.rb")).any? do |f|
|
|
85
|
+
File.read(f).match?(/add_column\s+:#{table_name},\s*:#{column}\b/)
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
class Add<%= column.camelize %>To<%= table_name.camelize %> < ActiveRecord::Migration<%= migration_version %>
|
|
2
|
+
def change
|
|
3
|
+
add_column :<%= table_name %>, :<%= column %>, "geometry(<%= geometry_type %>,4326)"
|
|
4
|
+
add_index :<%= table_name %>, :<%= column %>, using: :gist
|
|
5
|
+
end
|
|
6
|
+
end
|
data/llms.txt
CHANGED
|
@@ -5,10 +5,9 @@
|
|
|
5
5
|
## Install (exact steps)
|
|
6
6
|
|
|
7
7
|
1. Gemfile: `gem "active_map"`; run `bundle install`.
|
|
8
|
-
2. `bin/rails g active_map:install` — idempotent; mounts engine at `/maps`, writes `config/initializers/active_map.rb` and `app/maps/sample_map.rb`, pins/registers the Stimulus controller when `config/importmap.rb` / `app/javascript/controllers/index.js` exist.
|
|
9
|
-
3.
|
|
10
|
-
`add_column :warehouses, :coordinates, "geometry(Point,4326)"` + `add_index :warehouses, :coordinates, using: :gist`.
|
|
11
|
-
Column types: `geometry(Point,4326)`, `geometry(Polygon,4326)`, `geometry(LineString,4326)`.
|
|
8
|
+
2. `bin/rails g active_map:install` — idempotent; mounts engine at `/maps`, writes `config/initializers/active_map.rb` and `app/maps/sample_map.rb`, generates a PostGIS-enable migration, and pins/registers the Stimulus controller when `config/importmap.rb` / `app/javascript/controllers/index.js` exist. Then `bin/rails db:migrate`.
|
|
9
|
+
3. Make a model mappable: `bin/rails g active_map:mappable Warehouse coordinates:point` (shape = point|polygon|line) — adds the geometry column migration (with GiST index) and injects `acts_as_mappable`; creates the model if absent; idempotent. Then `bin/rails db:migrate`.
|
|
10
|
+
Manual equivalent: `add_column :warehouses, :coordinates, "geometry(Point,4326)"` + `add_index :warehouses, :coordinates, using: :gist`. Column types: `geometry(Point,4326)`, `geometry(Polygon,4326)`, `geometry(LineString,4326)`.
|
|
12
11
|
4. Assign geometry with EWKT strings: `Warehouse.create!(coordinates: "SRID=4326;POINT(<lng> <lat>)")` — LNG FIRST in WKT.
|
|
13
12
|
|
|
14
13
|
## Model DSL
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: active_map
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.13.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Bryan
|
|
@@ -65,8 +65,12 @@ files:
|
|
|
65
65
|
- lib/active_map/version.rb
|
|
66
66
|
- lib/active_map/wkb.rb
|
|
67
67
|
- lib/generators/active_map/install/install_generator.rb
|
|
68
|
+
- lib/generators/active_map/install/templates/enable_postgis.rb.tt
|
|
68
69
|
- lib/generators/active_map/install/templates/initializer.rb
|
|
69
70
|
- lib/generators/active_map/install/templates/sample_map.rb
|
|
71
|
+
- lib/generators/active_map/mappable/mappable_generator.rb
|
|
72
|
+
- lib/generators/active_map/mappable/templates/add_geometry_column.rb.tt
|
|
73
|
+
- lib/generators/active_map/mappable/templates/model.rb.tt
|
|
70
74
|
- llms.txt
|
|
71
75
|
- vendor/active_map/MarkerCluster.Default.css
|
|
72
76
|
- vendor/active_map/MarkerCluster.css
|