Skip to content

Bind ActionView view layer into rbgo (require "action_view") - #195

Closed
tannevaled wants to merge 1 commit into
mainfrom
feat/bind-actionview
Closed

tannevaled wants to merge 1 commit into
mainfrom
feat/bind-actionview

Conversation

@tannevaled

Copy link
Copy Markdown
Contributor

Binds github.com/go-ruby-actionview/actionview (org go-ruby-actionview, repo actionview, pinned @main = 0e293ee) as a native module so require "action_view" resolves with no .rb file. This is the render bridge later actionpack/actionmailer bindings wire to.

Surface bound

  • ActiveSupport::SafeBuffer (aliased ActionView::OutputBuffer) — html-safe string with escape-on-concat << / concat / safe_concat / + / include?, plus String#html_safe / #html_safe?.
  • ActionView::Base view context:
    • tag helpers: content_tag (positional + block), tag, token_list / class_names, cdata_section;
    • url helpers: link_to (positional + block), mail_to, button_to, current_page?, url_for;
    • form_tag family: text_field_tag/password_field_tag/hidden_field_tag/text_area_tag/check_box_tag/radio_button_tag/select_tag/label_tag/submit_tag/button_tag, options_for_select, form_tag;
    • form_with yielding an ActionView::Helpers::FormBuilder (text_field, password_field, hidden_field, text_area, label, check_box, radio_button, select, submit, object_name/field_name/field_id);
    • text helpers: truncate, pluralize, simple_format, word_wrap, highlight, excerpt;
    • number helpers: number_to_currency, number_with_delimiter/number_to_delimited, number_with_precision/number_to_rounded, number_to_percentage, number_to_human_size, number_to_human.
  • ActionView::PartialIteration (index/size/first?/last?) for collection partials.

All observable output (tag_options rendering, user[name]/user_name conventions, currency/number formatting, SafeBuffer escaping) is produced by the pure-Go library; this PR is the argument mapping + result wrapping.

Seams

  • URLFor (routes) — wires to a Ruby url_for= callable when set, else the identity/path default.
  • RenderTemplate — wires to a Ruby render_template= callable when set (the hook actionpack overrides with its own resolver), else an inline-ERB default that compiles the template through the already-bound go-ruby-erb compiler (erubi mode) and evaluates it with the render locals bound and self = the Base, so <%= %> runs Ruby (helpers dispatch, @ivars resolve via a new ivarTable case, collection _counter/_iteration locals bound). Split into open/closed build variants like the Sinatra erb helper.
  • #render stays a plain dispatchable method — a later actionpack/actionmailer binding renders a view by sending :render to a Base whose render_template callable is wired, so the whole pipeline funnels through one method.

Wiring

  • providedFeatures: action_view + actionview.
  • registerActionView() runs after registerActiveSupport (SafeBuffer nests under ActiveSupport) and after the bootstrap ERB/Erubi registration.
  • classOf: cases for *SafeBufferVal / *ActionViewBase / *AVPartialIter / *FormBuilderVal; ivarTable: case for *ActionViewBase; arith operator fast-path: + on *SafeBufferVal dispatches as a method (so views build markup with f.label + f.text_field).

Verification

  • 100% coverage of the new actionview*.go files (51 functions), including the SafeBuffer escaping, every helper family, the URLFor/RenderTemplate seam branches (Ruby-callable + default), and the three inline-render error branches (fault-injected erb-compile / parse / compile failures).
  • Full internal/vm + internal/object suites green; gofmt -l clean; go vet clean; builds on all six 64-bit arches (amd64/arm64/riscv64/loong64/ppc64le/s390x) and under -tags rbgo_closed.

🤖 Generated with Claude Code

Bind github.com/go-ruby-actionview/actionview as a native module so
`require "action_view"` works with no .rb file. ActionView::Base is the
view context exposing the pure tag/url/form/text/number helpers
(delegating to the library package functions) alongside the stateful
helpers (button_to, form_tag, form_with, current_page?, render) that
build a fresh library Context per call from the instance configuration.

Surface bound:
  - ActiveSupport::SafeBuffer (+ ActionView::OutputBuffer alias) with
    escape-on-concat << / concat / safe_concat / + and String#html_safe;
  - tag helpers content_tag/tag/token_list/class_names/cdata_section;
  - url helpers link_to/mail_to/button_to/current_page?/url_for;
  - form_tag-family inputs, select_tag, submit/button, options_for_select,
    form_tag, and form_with yielding an ActionView::Helpers::FormBuilder;
  - text helpers truncate/pluralize/simple_format/word_wrap/highlight/
    excerpt and the eight NumberHelper formatters;
  - ActionView::PartialIteration for collection partials.

Seams: URLFor (routes) wires to a Ruby url_for= callable, else the
identity/path default; RenderTemplate wires to a Ruby render_template=
callable, else an inline-ERB default that evaluates the template through
the already-bound go-ruby-erb compiler so <%= %> runs Ruby against the
view context (binding-scoped locals + @Ivars via the ivarTable seam).
#render stays an ordinary dispatchable method so a later actionpack/
actionmailer binding renders a view by sending :render to a Base.

100% coverage of the new files; full internal/vm + internal/object
suites green; gofmt/vet clean; builds on all six 64-bit arches and under
the closed-world build tag.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@tannevaled

Copy link
Copy Markdown
Contributor Author

Superseded by the wave-2 consolidation PR (single merge onto main; shared builtins/require/object_model/vm/arith/digest_bind). Work preserved verbatim; branch kept for reference.

@tannevaled tannevaled closed this Jul 6, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant