[openstreetmap/openstreetmap-website] Adds note tags support (PR #5344)
Emin Kocan
notifications at github.com
Tue Dec 3 12:45:03 UTC 2024
@kcne commented on this pull request.
> @@ -14,6 +14,10 @@ xml.note("lon" => note.lon, "lat" => note.lat) do
xml.date_closed note.closed_at if note.closed?
+ note.tags.each do |k, v|
This code is duplicated multiple times, consider creating a shared helper method to reuse instead.
> + validates :note, :associated => true
+ validates :k, :v, :allow_blank => true, :length => { :maximum => 255 }, :characters => true
+ validates :k, :uniqueness => { :scope => :note_id }
To ensure stronger data integrity, we can enforce that k and v are always present, within length limits, and unique per note. Additionally, using `presence: true` for note simplifies and improves performance compared to `associated: true`
```ruby
validates :note, presence: true
validates :k, presence: true, length: { maximum: 255 }, uniqueness: { scope: :note_id }
validates :v, presence: true, length: { maximum: 255 }
```
> +class CreateNoteTags < ActiveRecord::Migration[7.2]
+ def change
+ # Create a table and primary key
+ create_table :note_tags, :primary_key => [:note_id, :k] do |t|
+ t.column "note_id", :bigint, :null => false
+ t.column "k", :string, :default => "", :null => false
+ t.column "v", :string, :default => "", :null => false
+
+ t.foreign_key :notes, :column => :note_id, :name => "note_tags_id_fkey"
+ end
+ end
+end
This migration works well for ensuring uniqueness with a composite primary key. However, if querying by tags (e.g., `{k: "created_by", v: "openstreetmap"}`) is expected, a surrogate primary key (`id`) with additional indexes might be more efficient. For example:
```ruby
create_table :note_tags do |t|
t.bigint :note_id, null: false
t.string :k, null: false, default: ""
t.string :v, null: false, default: ""
t.timestamps
end
add_index :note_tags, [:note_id, :k], unique: true # Enforce uniqueness
add_index :note_tags, [:k, :v] # Optimize tag-based queries
```
This approach aligns with Rails conventions, simplifies queries, and allows adding indexes for tag lookups (`k`/`v`).
> @@ -83,12 +85,30 @@ def create
lat = OSM.parse_float(params[:lat], OSM::APIBadUserInput, "lat was not a number")
comment = params[:text]
+ # Extract the tags parameter (if it exists)
+ tags = []
+ if params[:tags].present?
+ # Split by commas to get individual key-value pairs
+ pairs = params[:tags].split(",")
+
+ # For each pair in parameters, store it in tags variable
+ pairs.each do |pair|
+ key, value = pair.split(":", 2)
+ tags << { :k => sanitize(key), :v => sanitize(value) } if key && value
+ end
+ end
I agree with Tom here. Also independent of implementation, validation here would be necessary in my opinion.
Two alternative approaches that could be useful here is to:
- use nested form parameters:
```
tags[created_by]=OpenStreetMap-Website&tags[editor]=JOSM
```
- using a prefix for tag related properties:
```
tag_created_by=OpenStreetMap-Website&tag_editor=JOSM
```
--
Reply to this email directly or view it on GitHub:
https://github.com/openstreetmap/openstreetmap-website/pull/5344#pullrequestreview-2475434346
You are receiving this because you are subscribed to this thread.
Message ID: <openstreetmap/openstreetmap-website/pull/5344/review/2475434346 at github.com>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openstreetmap.org/pipermail/rails-dev/attachments/20241203/41fe5d17/attachment.htm>
More information about the rails-dev
mailing list