Make address optional, add from Today tab, GPS update on details #29
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "26-optional-address"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Changes
app/models/property.rb: removedvalidates :address_line, presence: trueapp/controllers/properties_controller.rb: resolve action handles missing address paramsapp/controllers/work_queue_items_controller.rb: create action acceptsclient_nameto make new propertyapp/javascript/controllers/location_controller.js: save without GPS/address, graceful nil handlingapp/javascript/controllers/add_location_controller.js: new Stimulus controller for GPS address updateapp/views/properties/show.html.erb: Update Address button, nil-safe displayapp/views/properties/manage.html.erb: nil-safe address displayapp/views/work_queue_items/_queue_item.html.erb: name as primary, links to detailsapp/views/work_queue_items/_property_item.html.erb: name as primary, nil-safeapp/views/work_queue_items/index.html.erb: quick-add form, "Recent" headingapp/views/work_queue_items/create.turbo_stream.erb: handle new property in Turbo Streamapp/assets/stylesheets/application.css: styles for quick-add, detail-actions, btn-link.gitignore: added.playwright-mcp/and*.pngTest Plan
Review Checklist
Related Notes
ldraney/landscaping-assistant #26— optional addressldraney/landscaping-assistant #27— add from Today tablandscaping-assistant— projectCloses #26
Closes #27
PR #29 Review
DOMAIN REVIEW
Tech stack: Ruby on Rails 7 (Hotwire/Turbo Streams, Stimulus JS, ERB views). Reviewing for Rails controller safety, Stimulus correctness, view nil-safety, XSS risk, and Turbo Stream correctness.
Rails Controller Safety
properties_controller.rb#resolve(line 39-46): Theelsebranch has dead code --has_addressis alwaysfalsein this branch, sohas_address ? "#{number} #{street}" : nilwill always benil. Harmless but confusing; should just beaddress_line: nil.work_queue_items_controller.rb#create(line 15-16):Property.create!with onlyclient_namewill raiseActiveRecord::RecordInvalidon any validation failure and return a 500. There is no rescue. For a quick-add form this is low risk (onlyclient_namepresence is validated and we guard withparams[:client_name].present?), but an empty-string-with-whitespace like" "would slip past thepresent?check but fail the model validation. Consider.stripbefore the check or a rescue with user-facing error.properties_controller.rb#resolve: No strong parameters -- rawparams[:street],params[:city], etc. are used directly. This is acceptable for a JSON API endpoint that only inserts into permitted model attributes via the model layer, but it bypasses Rails' conventional mass-assignment protection pattern. Not a blocker since each attribute is explicitly assigned, but worth noting.Stimulus Controller Correctness
add_location_controller.js: Targets and values declared correctly. Thesave()method referencesthis.street.road(line 62) which would throw ifdetect()was never called or geocoding failed. However, theformSectionis hidden until geocoding succeeds, so user cannot reachsave()withoutthis.streetbeing set. Safe in practice.add_location_controller.jsline 51:document.querySelector("meta[name='csrf-token']").content-- if the meta tag is missing (e.g., API-only page), this throws. Low risk for this app.View Nil-Safety
toggle_active.turbo_stream.erb(lines 11, 34): Both the active and inactive branches still use<%= @property.address_line %> · <%= @property.city %>WITHOUT the nil-safe pattern used everywhere else. Whenaddress_lineis nil, this renders " · " (empty dot). This is inconsistent with the rest of the PR which usesproperty.address_line.present? ? ... : "No address yet". This is a bug for properties created without an address.XSS Risk
location_controller.jsrenderRecent(): UsestextContentfor all dynamic values (line 135, 139) -- safe, no innerHTML. Theadd_location_controller.jsalso usestextContent(lines 32-33). No XSS vectors found.Turbo Stream Correctness
create.turbo_stream.erb: The@new_propertyinstance variable is set in the controller and correctly used in the template.prepend "property-list"targets the correct DOM ID fromindex.html.erbline 50. Thereplacefor existing properties targetsproperty_#{id}which matches_property_item.html.erbline 1. Correct.BLOCKERS
Broken test:
spec/models/property_spec.rblines 4-7 explicitly testvalidates :address_line, presence: true-- a validation that this PR removes. This test will now FAIL. The test must be updated to reflect that address_line is optional. Additionally, tests on lines 18, 30-31, and 39 create properties withaddress_linewhich is fine, but there should be a NEW test asserting that a property IS valid without an address_line. The existing test suite is now incorrect.Nil-safety gap in
toggle_active.turbo_stream.erb: Lines 11 and 34 still render@property.address_linewithout a nil guard. A property without an address that gets toggled active/inactive will render broken markup (" · "). This template was touched in this PR (it was refactored into the if/else split), so it should have received the same nil-safe treatment applied to every other template.NITS
properties_controller.rbline 42: Dead ternaryhas_address ? "#{number} #{street}" : nil--has_addressis always false in that branch. Simplify to justnil.work_queue_items/index.html.erbquick-add form: No client-side validation orrequiredattribute on the input. Submitting an empty form will create aProperty.create!(client_name: "")call that fails with 500 since model validates presence. Addrequiredto the input for graceful UX.The heading change from "All Properties" to "Recent" (index.html.erb line 32) may confuse users -- the list still shows ALL active properties ordered by
updated_at, not a "recent" subset. Consider matching label to behavior.CSS:
btn-deactivateopacity 0.4 is very low for touch targets on mobile -- may be hard to discover. Consider at least 0.5 or a different affordance.SOP COMPLIANCE
26-optional-addressmatches issue #26).gitignorefor playwright artifacts is reasonable)PROCESS OBSERVATIONS
toggle_active.turbo_stream.erbrefactor (if/else split + turbo_stream.remove) appears related to issue #24 scope (deactivate from Today tab), which is scope creep into this PR. It works correctly for that feature but expands the review surface.VERDICT: NOT APPROVED
Two blockers must be addressed:
spec/models/property_spec.rb-- remove the address_line presence test, add a test for valid property without address_line.toggle_active.turbo_stream.erb(both branches, lines 11 and 34) to match the pattern used in all other templates.