Module: Basecamp::Services::CardsExtensions
- Defined in:
- lib/basecamp/services/cards_extensions.rb
Overview
Tri-state due_on for card updates, prepended onto the generated
CardsService (see the on_load hook in basecamp.rb).
BC3's card controller is presence-aware on the JSON representation
(+kanban/cards_controller.rb+, basecamp/bc3#12521): card_update_params
is plain card_params, so an update writes exactly the keys the body
carries. An omitted due_on leaves the card's due date UNCHANGED; an
explicit "" (or null) clears it. The
{ due_on: nil }.merge(card_params) default survives only for the
HTML/turbo_stream web forms, which post every field on every submit.
A clear therefore has to be stated, never encoded as an omission —
omitting due_on to clear it is a silent no-op. "" is the
spelling that travels: JSON null cannot reach the wire from here at
all, because compact_params is kwargs.compact and drops nils (SPEC
section 18 body compaction). Rails casts the blank string to nil on the
date column, so "" is what a clear looks like end to end.
There is no read-before-write. An earlier version GET the card and resent its due date, because the server then nil'd an unmentioned one and a sparse PUT was destructive. Presence-awareness removed the hazard the extra round-trip covered, and with it the race the round-trip opened between the read and the write. Every case is a single PUT.
Instance Method Summary collapse
-
#update(card_id:, title: nil, content: nil, due_on: nil, assignee_ids: nil) ⇒ Hash
Updates a card, addressing only what the caller named.
Instance Method Details
#update(card_id:, title: nil, content: nil, due_on: nil, assignee_ids: nil) ⇒ Hash
Updates a card, addressing only what the caller named.
due_on is tri-state:
nil(unaddressed) — nodue_onkey is sent; BC3 leaves the current due date alone- "" — a stated clear, sent as ""
- a date — the due date is set
Every other argument is plain send-when-set: nil leaves the field off
the body, and BC3 leaves the stored value untouched.
This is the same single PUT as #update_verbatim, which stays as the
unnormalised path; update differs only in mapping an empty due_on to
the "" the server reads as a clear.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
# File 'lib/basecamp/services/cards_extensions.rb', line 51 def update(card_id:, title: nil, content: nil, due_on: nil, assignee_ids: nil) resolved_due_on = if due_on.nil? # Unaddressed. +compact_params+ drops the nil, so no key is sent and # the presence-aware update never touches the stored date. nil elsif due_on.to_s.empty? # A stated clear. "" survives +compact_params+ (it removes only # nils) and reaches the wire as {"due_on": ""}. "" else due_on end update_verbatim( card_id: card_id, title: title, content: content, due_on: resolved_due_on, assignee_ids: assignee_ids ) end |