feat: ruby (Rails + Pundit + CanCanCan + Devise) structural support#96
Conversation
Wires up the `tree-sitter-ruby` grammar and ships nine TOML rules covering the dominant Ruby authz idioms: Rails `before_action` / `skip_before_action` filters, Pundit (`authorize`, `policy(...).<action>?`, `*Policy < ApplicationPolicy`), CanCanCan (`can :read, Article`, `user.can?(:x, ...)`), Devise-style role predicates (`current_user.admin?`), and inline RBAC shapes (`user.role == "admin"`/`:admin`, `user.roles.include?(...)`). Calibrated on `discourse/discourse` (10K Ruby files, 339 findings) — see `docs/corpus/ruby.md` for the run, top filter names, and the known `Guardian.*?` follow-up gap.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
📝 WalkthroughWalkthroughAdds tree-sitter-based structural Ruby support: dependency and parser wiring, nine TOML authorization rules (Pundit/CanCanCan/Rails/Devise/role patterns) with templates and tests, and documentation/corpus updates promoting Ruby to structural scanning (v0.2). ChangesRuby Structural Scanner Support
Sequence Diagram(s)sequenceDiagram
participant Cargo as Cargo.toml
participant Discovery as src/scanner/discovery.rs
participant Parser as src/scanner/parser.rs
participant Embedded as src/rules/embedded.rs
participant Matcher as src/scanner/matcher.rs
Cargo->>Discovery: add tree-sitter-ruby dependency
Discovery->>Parser: detect .rb/.rake/Rakefile -> Language::Ruby
Parser->>Embedded: map Language::Ruby -> tree-sitter-ruby grammar
Embedded->>Matcher: register ruby-*.toml embedded rules
Matcher->>Matcher: run Ruby rule tests via parse_and_match_ruby
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
This PR successfully implements structural scanner support for Ruby with comprehensive testing and proper integration. The implementation follows established patterns from other language integrations and includes extensive test coverage (22 Rust matcher tests + 33 inline TOML rule tests). No blocking defects were identified that would prevent merging.
You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/scanner/discovery.rs (1)
17-31:⚠️ Potential issue | 🟡 Minor | ⚡ Quick winAdd explicit support for extensionless
Rakefilein Ruby language detection
detect_languageis extension-based only (e.g., tests coverfoo.rbandRakefile.rake, but no logic exists to match a bareRakefilefilename). Extend detection (and add a test likedetect_language(Path::new("Rakefile")) == Some((Language::Ruby, false))) to cover Rails’ common extensionless entrypoint.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/scanner/discovery.rs` around lines 17 - 31, detect_language currently only checks extensions; add a special-case filename check so an extensionless "Rakefile" is detected as Ruby. In function detect_language, before or alongside the extension extraction, inspect the file name/stem (e.g., using path.file_name()/to_str()) and if it equals "Rakefile" return Some((Language::Ruby, false)); keep existing extension-based matching for "rake" and "rb" intact and ensure the new check handles case-sensitivity if needed for tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/scanner/discovery.rs`:
- Around line 17-31: detect_language currently only checks extensions; add a
special-case filename check so an extensionless "Rakefile" is detected as Ruby.
In function detect_language, before or alongside the extension extraction,
inspect the file name/stem (e.g., using path.file_name()/to_str()) and if it
equals "Rakefile" return Some((Language::Ruby, false)); keep existing
extension-based matching for "rake" and "rb" intact and ensure the new check
handles case-sensitivity if needed for tests.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 46ae534c-dee8-4c36-a75b-5aedc992d606
⛔ Files ignored due to path filters (1)
Cargo.lockis excluded by!**/*.lock
📒 Files selected for processing (20)
AGENTS.mdCargo.tomlREADME.mddocs/DESIGN.mddocs/corpus/README.mddocs/corpus/ruby.mdrules/ruby/cancancan-can-check.tomlrules/ruby/cancancan-can-declaration.tomlrules/ruby/current-user-role-predicate.tomlrules/ruby/pundit-authorize.tomlrules/ruby/pundit-policy-class.tomlrules/ruby/pundit-policy-method.tomlrules/ruby/rails-before-action-filter.tomlrules/ruby/role-collection-include.tomlrules/ruby/role-equals-check.tomlsrc/deep/candidate.rssrc/rules/embedded.rssrc/scanner/discovery.rssrc/scanner/matcher.rssrc/scanner/parser.rs
Bare Rakefile is the common Rails entrypoint and was previously ignored because detection was extension-only. Special-case the filename in both detect_language and detect_language_for_deep.
|
@coderabbitai Addressed in f9a7fd5:
|
|
Tip For best results, initiate chat on the files or code changes.
|
Summary
Structural scanner support for Ruby — wires up
tree-sitter-rubyand ships nine TOML rules covering Rails, Pundit, CanCanCan, Devise, and the inline RBAC idioms. Calibrated againstdiscourse/discourse(10K Ruby files, 339 findings) and thevarvet/pundittest fixtures.Changes
tree-sitter-rubyadded toCargo.toml;.rb/.rakemapped toLanguage::Rubyinsrc/scanner/discovery.rsandsrc/scanner/parser.rs; PHP becomes the new structural-canary inparse_sourcetests.rules/ruby/:pundit-authorize—authorize @post/authorize! :update, @articlepundit-policy-method—policy(@post).update?pundit-policy-class—class FooPolicy < ApplicationPolicycancancan-can-declaration—can :read, Articlecancancan-can-check—current_user.can?(:update, @post)(receiver pinned to principal-shaped names)rails-before-action-filter—before_action :require_admin/skip_before_action ...with an authz-name predicaterole-equals-check—user.role == "admin"/:adminrole-collection-include—current_user.roles.include?(:manager)current-user-role-predicate— Devise-stylecurrent_user.admin?obj.authorize, non-Policy classes,before_action :load_post,widget.can?, unrelatedtags.include?, non-role predicates).docs/corpus/ruby.mdcaptures the Discourse run with rule-by-rule and category breakdowns, top filter names, the policy-impl-path-skip note, and theGuardian.*?follow-up gap.AGENTS.md/README.md/docs/DESIGN.mdmove Ruby from "planned" to v0.2 shipped;src/deep/candidate.rsandsrc/scanner/discovery.rsdrop Ruby from the "no structural support" comments.Testing
cargo check— cleancargo clippy --all-features -- -D warnings— cleancargo fmt --check— cleancargo test --all-features— 466 unit + 18 + 6 + 6 + 10 integration tests passcargo run -- rules test— 461 inline rule tests passKnown gaps
Guardian.*?call-site shape (Discourse-specific but generalizable) — tracked in the corpus doc.before_actionfilter-name regex breadth catches Rails framework filters likecheck_xhrandverify_authenticity_token; deliberate for now, narrower variant deferred until a second corpus target's filter inventory.Closes #85
Summary by CodeRabbit
New Features
Documentation