Files
simply_based/spec/unsupported_view_spec.rb
T
bterkuileandClaude Sonnet 5 84c76bb093 Store: fail loudly on untranslatable views; quoting hardening; true batched bulk KV
- database.view now raises SimplyBased::UnsupportedView when a declared view
  carries CouchDB-era options the N1QL translation silently ignored before:
  :conditions (a JS fragment) and :emit_value, plus CouchDB list functions.
  Silently dropping :conditions was the worst of these — a
  'view :completed, key: :name, conditions: ...' query returned *unfiltered*
  results with no hint anything was wrong. Covered by unsupported_view_spec.
- All column/property names interpolated into N1QL are now routed through
  quote_ident, which rejects backticks/backslashes. These names come from the
  model DSL rather than user input, but a smuggled backtick must never become
  query text. Class names in index predicates go through a proper string
  literal quoting helper for the same reason.
- ensure_index: failures are still swallowed (an index build in progress must
  not take down queries) but now emit a warning naming the index, because the
  silent version left every subsequent query on a primary-index scan with no
  trace. The ensured-indexes bookkeeping is mutex-guarded for multithreaded
  servers (Puma).
- bulk_load / bulk_destroy now actually batch (collection.get_multi /
  remove_multi — one KV round trip). The README already advertised
  'bulk (batched KV)' but the code looped one get/remove per id.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-07-06 18:42:17 -05:00

35 lines
1.4 KiB
Ruby

require 'spec_helper'
class ConditionalViewWidget
include SimplyBased::Model
property :name
property :completed, type: :boolean
# A CouchDB-era declaration: the :conditions JavaScript fragment cannot be
# translated to N1QL. Declaring it must stay legal (simply_couch models load
# unchanged), but *querying* it must fail loudly — the previous behaviour
# silently dropped the condition and returned every document of the class.
view :completed_by_name, key: :name, conditions: 'doc.completed === true'
view :names_only, key: :name, emit_value: :name
end
RSpec.describe 'Untranslatable view declarations' do
it 'still allows the model to load and plain views to work' do
ConditionalViewWidget.create(name: 'a', completed: false)
expect(ConditionalViewWidget.all.size).to eq 1
end
it 'raises UnsupportedView when querying a :conditions view instead of silently ignoring the condition' do
ConditionalViewWidget.create(name: 'done', completed: true)
ConditionalViewWidget.create(name: 'done', completed: false)
expect {
ConditionalViewWidget.database.view(ConditionalViewWidget.completed_by_name(key: 'done'))
}.to raise_error(SimplyBased::UnsupportedView, /conditions/)
end
it 'raises UnsupportedView for :emit_value views' do
expect {
ConditionalViewWidget.database.view(ConditionalViewWidget.names_only(key: 'x'))
}.to raise_error(SimplyBased::UnsupportedView, /emit_value/)
end
end