[
  {
    "path": ".github/ISSUE_TEMPLATE/bug_report.md",
    "content": "---\nname: Bug report\nabout: Create a bug report to report a problem\ntitle: ''\nlabels: problem\nassignees: ''\n\n---\n\n**Describe the bug**\nA clear and concise description of what the bug is.\n\n**To Reproduce**\nSteps or runnable code to reproduce the problem.\n\n**Expected behavior**\nA clear and concise description of what you expected to happen.\n\n**Additional context**\nAdd any other context about the problem here.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/feature_request.md",
    "content": "---\nname: Feature request\nabout: Suggest an idea\ntitle: ''\nlabels: ['feature request']\nassignees: ''\n---\n\n**Please consider**\n- Could this feature break backwards-compatibility?\n- Could this feature benefit the many who use Pundit?\n- Could this feature be useful in _most_ projects that use Pundit?\n- Would this feature require Rails?\n- Am I open to creating a Pull Request with the necessary changes?\n\n**Is your feature request related to a problem? Please describe.**\nA clear and concise description of what the problem is. Ex. I'm always frustrated when [...]\n\n**Describe the solution you'd like**\nA clear and concise description of how you'd like to approach solving the problem.\n\n**Describe alternatives you've considered**\nA clear and concise description of any alternative solutions or features you've considered.\n\n**Additional context**\nAdd any other context. Ex. if you've solved this problem in your own projects already, how that worked, and why the feature should be moved and maintained in Pundit instead.\n"
  },
  {
    "path": ".github/PULL_REQUEST_TEMPLATE/gem_release_template.md",
    "content": "## To do\n\n- [ ] Make changes:\n  - [ ] Bump `Pundit::VERSION` in `lib/pundit/version.rb`.\n  - [ ] Update `CHANGELOG.md`.\n- [ ] Open pull request 🚀 and merge it.\n- [ ] Run [push gem](https://github.com/varvet/pundit/actions/workflows/push_gem.yml) GitHub Action.\n- [ ] Make an announcement in [Pundit discussions](https://github.com/varvet/pundit/discussions/categories/announcements)"
  },
  {
    "path": ".github/pull_request_template.md",
    "content": "## To do\n\n- [ ] I have read the [contributing guidelines](https://github.com/varvet/pundit/contribute).\n- [ ] I have added relevant tests.\n- [ ] I have adjusted relevant documentation.\n- [ ] I have made sure the individual commits are meaningful.\n- [ ] I have added relevant lines to the CHANGELOG.\n\nPS: Thank you for contributing to Pundit ❤️\n"
  },
  {
    "path": ".github/workflows/main.yml",
    "content": "name: Main\n\non:\n  push:\n    branches: [\"main\"]\n  pull_request:\n  workflow_dispatch:\n\npermissions:\n  contents: read\n\njobs:\n  matrix-test:\n    runs-on: ubuntu-latest\n    continue-on-error: ${{ matrix.allow-failure || false }}\n    strategy:\n      fail-fast: false\n      matrix:\n        ruby-version:\n          - \"3.2\"\n          - \"3.3\"\n          - \"3.4\"\n          - \"4.0\"\n          - \"jruby-9.4\"\n          - \"jruby\"\n        include: # HEAD-versions\n          - ruby-version: \"head\"\n            allow-failure: true\n          - ruby-version: \"jruby-head\"\n            allow-failure: true\n          - ruby-version: \"truffleruby-head\"\n            allow-failure: true\n\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up Ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          rubygems: latest\n          ruby-version: ${{ matrix.ruby-version }}\n          bundler-cache: true\n      - name: Run tests\n        run: bundle exec rspec\n\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up Ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          rubygems: latest\n          ruby-version: \"ruby\"\n          bundler-cache: true\n      - name: Run tests\n        run: bundle exec rspec\n        env:\n          COVERAGE: 1\n      - name: Upload coverage results\n        uses: actions/upload-artifact@v4\n        with:\n          include-hidden-files: true\n          name: coverage-results\n          path: coverage\n          retention-days: 1\n\n  linting:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up Ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          rubygems: default\n          ruby-version: \"ruby\"\n          bundler-cache: false\n      - run: bundle install\n      - name: Run standard\n        run: bundle exec standardrb\n\n  docs:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions/checkout@v4\n      - name: Set up Ruby\n        uses: ruby/setup-ruby@v1\n        with:\n          rubygems: default\n          ruby-version: \"ruby\"\n          bundler-cache: false\n      - run: bundle install\n      - run: rake yard\n\n  required-checks:\n    runs-on: ubuntu-latest\n    if: ${{ always() }}\n    needs:\n      - test\n      - matrix-test\n      - docs\n      - linting\n    steps:\n      - name: failure\n        if: ${{ failure() || contains(needs.*.result, 'failure') }}\n        run: exit 1\n      - name: success\n        run: exit 0\n"
  },
  {
    "path": ".github/workflows/push_gem.yml",
    "content": "name: Push Gem\n\non:\n  workflow_dispatch:\n\npermissions:\n  contents: read\n\njobs:\n  push:\n    if: github.repository == 'varvet/pundit'\n    runs-on: ubuntu-latest\n\n    permissions:\n      contents: write\n      id-token: write\n\n    steps:\n      # Set up\n      - name: Harden Runner\n        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1\n        with:\n          egress-policy: audit\n\n      - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7\n      - name: Set up Ruby\n        uses: ruby/setup-ruby@a6e6f86333f0a2523ece813039b8b4be04560854 # v1.190.0\n        with:\n          bundler-cache: true\n          ruby-version: ruby\n\n      # Release\n      - uses: rubygems/release-gem@612653d273a73bdae1df8453e090060bb4db5f31 # v1+ unreleased\n"
  },
  {
    "path": ".gitignore",
    "content": "*.gem\n*.rbc\n.bundle\n.config\n.coverage\n.yardoc\nGemfile.lock\nInstalledFiles\n_yardoc\ncoverage\ndoc/\nlib/bundler/man\npkg\nrdoc\nspec/reports\ntest/tmp\ntest/version_tmp\ntmp\n"
  },
  {
    "path": ".rubocop_ignore_git.yml",
    "content": "# This is here so we can keep YAML syntax highlight in the main file.\nAllCops:\n  Exclude:\n    - \"lib/generators/**/templates/**/*\"\n    <% `git status --ignored --porcelain`.lines.grep(/^!! /).each do |path| %>\n    - <%= path.sub(/^!! /, '').sub(/\\/$/, '/**/*') %>\n    <% end %>\n"
  },
  {
    "path": ".standard.yml",
    "content": "parallel: true\nruby_version: 3.2\n\nextend_config:\n  - .rubocop_ignore_git.yml\n"
  },
  {
    "path": ".yardopts",
    "content": "--no-private --private --protected --hide-void-return --markup markdown --fail-on-warning\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Pundit\n\n## Unreleased\n\n- Add support for `params.expect` using `expected_parameters` and `expected_parameters_for`. [#855](https://github.com/varvet/pundit/pull/855)\n\n### Fixed\n- Update for rspec 4 breaking changes [#873](https://github.com/varvet/pundit/issues/873)\n\n## 2.5.2 (2025-09-24)\n\n### Fixed\n- Added `config/rubocop-rspec.yml` back from accidentally being excluded [#866](https://github.com/varvet/pundit/issues/866)\n\n## 2.5.1 (2025-09-12)\n\n### Fixed\n- Requiring only `pundit/rspec` no longer raises an error in Active Support [#857](https://github.com/varvet/pundit/issues/857)\n\n## 2.5.0 (2025-03-03)\n\n### Added\n\n- Add `Pundit::Authorization#pundit_reset!` hook to reset the policy and policy scope cache. [#830](https://github.com/varvet/pundit/issues/830)\n- Add links to gemspec. [#845](https://github.com/varvet/pundit/issues/845)\n- Register policies directories for Rails 8 code statistics [#833](https://github.com/varvet/pundit/issues/833)\n- Added an example for how to use pundit with Rails 8 authentication generator [#850](https://github.com/varvet/pundit/issues/850)\n\n### Changed\n\n- Deprecated `Pundit::SUFFIX`, moved it to `Pundit::PolicyFinder::SUFFIX` [#835](https://github.com/varvet/pundit/issues/835)\n- Explicitly require less of `active_support` [#837](https://github.com/varvet/pundit/issues/837)\n- Using `permit` matcher without a surrouding `permissions` block now raises a useful error. [#836](https://github.com/varvet/pundit/issues/836)\n\n### Fixed\n\n- Using a hash as custom cache in `Pundit.authorize` now works as documented. [#838](https://github.com/varvet/pundit/issues/838)\n\n## 2.4.0 (2024-08-26)\n\n### Changed\n\n- Improve the `NotAuthorizedError` message to include the policy class.\n  Furthermore, in the case where the record passed is a class instead of an instance, the class name is given. [#812](https://github.com/varvet/pundit/issues/812)\n\n### Added\n\n- Add customizable permit matcher description [#806](https://github.com/varvet/pundit/issues/806)\n- Add support for filter_run_when_matching :focus with permissions helper. [#820](https://github.com/varvet/pundit/issues/820)\n\n## 2.3.2 (2024-05-08)\n\n- Refactor: First pass of Pundit::Context [#797](https://github.com/varvet/pundit/issues/797)\n\n### Changed\n\n- Update `ApplicationPolicy` generator to qualify the `Scope` class name [#792](https://github.com/varvet/pundit/issues/792)\n- Policy generator uses `NoMethodError` to indicate `#resolve` is not implemented [#776](https://github.com/varvet/pundit/issues/776)\n\n## Deprecated\n\n- Dropped support for Ruby 3.0 [#796](https://github.com/varvet/pundit/issues/796)\n\n## 2.3.1 (2023-07-17)\n\n### Fixed\n\n- Use `Kernel.warn` instead of `ActiveSupport::Deprecation.warn` for deprecations [#764](https://github.com/varvet/pundit/issues/764)\n- Policy generator now works on Ruby 3.2 [#754](https://github.com/varvet/pundit/issues/754)\n\n## 2.3.0 (2022-12-19)\n\n### Added\n\n- add support for rubocop-rspec syntax extensions [#745](https://github.com/varvet/pundit/issues/745)\n\n## 2.2.0 (2022-02-11)\n\n### Fixed\n\n- Using `policy_class` and a namespaced record now passes only the record when instantiating the policy. (#697, #689, #694, #666)\n\n### Changed\n\n- Require users to explicitly define Scope#resolve in generated policies (#711, #722)\n\n### Deprecated\n\n- Deprecate `include Pundit` in favor of `include Pundit::Authorization` [#621](https://github.com/varvet/pundit/issues/621)\n\n## 2.1.1 (2021-08-13)\n\nFriday 13th-release!\n\nCareful! The bugfix below [#626](https://github.com/varvet/pundit/issues/626) could break existing code. If you rely on the\nreturn value for `authorize` and namespaced policies you might need to do some\nchanges.\n\n### Fixed\n\n- `.authorize` and `#authorize` return the instance, even for namespaced\n  policies [#626](https://github.com/varvet/pundit/issues/626)\n\n### Changed\n\n- Generate application scope with `protected` attr_readers. [#616](https://github.com/varvet/pundit/issues/616)\n\n### Removed\n\n- Dropped support for Ruby end-of-life versions: 2.1 and 2.2. [#604](https://github.com/varvet/pundit/issues/604)\n- Dropped support for Ruby end-of-life versions: 2.3 [#633](https://github.com/varvet/pundit/issues/633)\n- Dropped support for Ruby end-of-life versions: 2.4, 2.5 and JRuby 9.1 [#676](https://github.com/varvet/pundit/issues/676)\n- Dropped support for RSpec 2 [#615](https://github.com/varvet/pundit/issues/615)\n\n## 2.1.0 (2019-08-14)\n\n### Fixed\n\n- Avoid name clashes with the Error class. [#590](https://github.com/varvet/pundit/issues/590)\n\n### Changed\n\n- Return a safer default NotAuthorizedError message. [#583](https://github.com/varvet/pundit/issues/583)\n\n## 2.0.1 (2019-01-18)\n\n### Breaking changes\n\nNone\n\n### Other changes\n\n- Improve exception handling for `#policy_scope` and `#policy_scope!`. [#550](https://github.com/varvet/pundit/issues/550)\n- Add `:policy` metadata to RSpec template. [#566](https://github.com/varvet/pundit/issues/566)\n\n## 2.0.0 (2018-07-21)\n\nNo changes since beta1\n\n## 2.0.0.beta1 (2018-07-04)\n\n### Breaking changes\n\n- Only pass last element of \"namespace array\" to policy and scope. [#529](https://github.com/varvet/pundit/issues/529)\n- Raise `InvalidConstructorError` if a policy or policy scope with an invalid constructor is called. [#462](https://github.com/varvet/pundit/issues/462)\n- Return passed object from `#authorize` method to make chaining possible. [#385](https://github.com/varvet/pundit/issues/385)\n\n### Other changes\n\n- Add `policy_class` option to `authorize` to be able to override the policy. [#441](https://github.com/varvet/pundit/issues/441)\n- Add `policy_scope_class` option to `authorize` to be able to override the policy scope. [#441](https://github.com/varvet/pundit/issues/441)\n- Fix `param_key` issue when passed an array. [#529](https://github.com/varvet/pundit/issues/529)\n- Allow specification of a `NilClassPolicy`. [#525](https://github.com/varvet/pundit/issues/525)\n- Make sure `policy_class` override is called when passed an array. [#475](https://github.com/varvet/pundit/issues/475)\n\n- Use `action_name` instead of `params[:action]`. [#419](https://github.com/varvet/pundit/issues/419)\n- Add `pundit_params_for` method to make it easy to customize params fetching. [#502](https://github.com/varvet/pundit/issues/502)\n\n## 1.1.0 (2016-01-14)\n\n- Can retrieve policies via an array of symbols/objects.\n- Add autodetection of param key to `permitted_attributes` helper.\n- Hide some methods which should not be actions.\n- Permitted attributes should be expanded.\n- Generator uses `RSpec.describe` according to modern best practices.\n\n## 1.0.1 (2015-05-27)\n\n- Fixed a regression where NotAuthorizedError could not be ininitialized with a string.\n- Use `camelize` instead of `classify` for symbol policies to prevent weird pluralizations.\n\n## 1.0.0 (2015-04-19)\n\n- Caches policy scopes and policies.\n- Explicitly setting the policy for the controller via `controller.policy = foo` has been removed. Instead use `controller.policies[record] = foo`.\n- Explicitly setting the policy scope for the controller via `controller.policy_policy = foo` has been removed. Instead use `controller.policy_scopes[scope] = foo`.\n- Add `permitted_attributes` helper to fetch attributes from policy.\n- Add `pundit_policy_authorized?` and `pundit_policy_scoped?` methods.\n- Instance variables are prefixed to avoid collisions.\n- Add `Pundit.authorize` method.\n- Add `skip_authorization` and `skip_policy_scope` helpers.\n- Better errors when checking multiple permissions in RSpec tests.\n- Better errors in case `nil` is passed to `policy` or `policy_scope`.\n- Use `inspect` when printing object for better errors.\n- Dropped official support for Ruby 1.9.3\n\n## 0.3.0 (2014-08-22)\n\n- Extend the default `ApplicationPolicy` with an `ApplicationPolicy::Scope` [#120](https://github.com/varvet/pundit/issues/120)\n- Fix RSpec 3 deprecation warnings for built-in matchers [#162](https://github.com/varvet/pundit/issues/162)\n- Generate blank policy spec/test files for Rspec/MiniTest/Test::Unit in Rails [#138](https://github.com/varvet/pundit/issues/138)\n\n## 0.2.3 (2014-04-06)\n\n- Customizable error messages: `#query`, `#record` and `#policy` methods on `Pundit::NotAuthorizedError` [#114](https://github.com/varvet/pundit/issues/114)\n- Raise a different `Pundit::AuthorizationNotPerformedError` when `authorize` call is expected in controller action but missing [#109](https://github.com/varvet/pundit/issues/109)\n- Update Rspec matchers for Rspec 3 [#124](https://github.com/varvet/pundit/issues/124)\n\n## 0.2.2 (2014-02-07)\n\n- Customize the user to be passed into policies: `pundit_user` [#42](https://github.com/varvet/pundit/issues/42)\n"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Contributor Code of Conduct\n\nAs contributors and maintainers of this project, we pledge to respect all\npeople who contribute through reporting issues, posting feature requests,\nupdating documentation, submitting pull requests or patches, and other\nactivities.\n\nWe are committed to making participation in this project a harassment-free\nexperience for everyone, regardless of level of experience, gender, gender\nidentity and expression, sexual orientation, disability, personal appearance,\nbody size, race, age, or religion.\n\nExamples of unacceptable behavior by participants include the use of sexual\nlanguage or imagery, derogatory comments or personal attacks, trolling, public\nor private harassment, insults, or other unprofessional conduct.\n\nProject maintainers have the right and responsibility to remove, edit, or\nreject comments, commits, code, wiki edits, issues, and other contributions\nthat are not aligned to this Code of Conduct. Project maintainers who do not\nfollow the Code of Conduct may be removed from the project team.\n\nInstances of abusive, harassing, or otherwise unacceptable behavior may be\nreported by opening an issue or contacting one or more of the project\nmaintainers.\n\nThis Code of Conduct is adapted from the [Contributor\nCovenant](http:contributor-covenant.org), version 1.0.0, available at\n[https://contributor-covenant.org/version/1/0/0/](https://contributor-covenant.org/version/1/0/0/)\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "## Security issues\n\nIf you have found a security related issue, please do not file an issue on GitHub or send a PR addressing the issue. Refer to [SECURITY.md](./SECURITY.md) for instructions.\n\n## Reporting issues\n\nPlease try to answer the following questions in your bug report:\n\n- What did you do?\n- What did you expect to happen?\n- What happened instead?\n\nMake sure to include as much relevant information as possible. Ruby version,\nPundit version, OS version and any stack traces you have are very valuable.\n\n## Pull Requests\n\n- **Add tests!** Your patch won't be accepted if it doesn't have tests.\n\n- **Document any change in behaviour**. Make sure the README and any other\n  relevant documentation are kept up-to-date.\n\n- **Create topic branches**. Please don't ask us to pull from your main branch.\n\n- **One pull request per feature**. If you want to do more than one thing, send\n  multiple pull requests.\n\n- **Send coherent history**. Make sure each individual commit in your pull\n  request is meaningful. If you had to make multiple intermediate commits while\n  developing, please squash them before sending them to us.\n- **Update the CHANGELOG.** Don't forget to add your new changes to the CHANGELOG.\n"
  },
  {
    "path": "Gemfile",
    "content": "# frozen_string_literal: true\n\nsource \"https://rubygems.org\"\n\ngemspec\n\n# Rails-related - for testing purposes\ngem \"actionpack\", \">= 3.0.0\" # Used to test strong parameters\ngem \"activemodel\", \">= 3.0.0\" # Used to test ActiveModel::Naming\ngem \"railties\", \">= 3.0.0\" # Used to test generators\n\n# Testing\ngem \"rspec\", \">= 3.0.0\"\ngem \"simplecov\", \">= 0.17.0\"\n\n# Development tools\ngem \"bundler\"\ngem \"rake\"\ngem \"standard\"\ngem \"yard\"\ngem \"zeitwerk\"\n\n# Affects us on JRuby 9.3.15.\n#\n# @see https://github.com/rails/rails/issues/54260\ngem \"logger\"\n"
  },
  {
    "path": "LICENSE.txt",
    "content": "Copyright (c) 2019 Jonas Nicklas, Varvet AB\n\nMIT License\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Pundit\n\n[![Main](https://github.com/varvet/pundit/actions/workflows/main.yml/badge.svg)](https://github.com/varvet/pundit/actions/workflows/main.yml)\n[![Inline docs](https://inch-ci.org/github/varvet/pundit.svg?branch=main)](https://inch-ci.org/github/varvet/pundit)\n[![Gem Version](https://badge.fury.io/rb/pundit.svg)](https://badge.fury.io/rb/pundit)\n\nPundit provides a set of helpers which guide you in leveraging regular Ruby\nclasses and object oriented design patterns to build a straightforward, robust, and\nscalable authorization system.\n\n## Links:\n\n- [API documentation for the most recent version](https://www.rubydoc.info/gems/pundit)\n- [Source Code](https://github.com/varvet/pundit)\n- [Contributing](https://github.com/varvet/pundit/blob/main/CONTRIBUTING.md)\n- [Code of Conduct](https://github.com/varvet/pundit/blob/main/CODE_OF_CONDUCT.md)\n\n<strong>Sponsored by:</strong> <a href=\"https://www.varvet.com\">Varvet<br><br><img src=\"https://github.com/varvet/pundit/assets/99166/aa9efa0a-6903-4037-abee-1824edc57f1a\" alt=\"Varvet logo\" height=\"120\"></div>\n\n## Installation\n\n> **Please note** that the README on GitHub is accurate with the _latest code on GitHub_. You are most likely using a released version of Pundit, so please refer to the [documentation for the latest released version of Pundit](https://www.rubydoc.info/gems/pundit).\n\n``` sh\nbundle add pundit\n```\n\nInclude `Pundit::Authorization` in your application controller:\n\n``` ruby\nclass ApplicationController < ActionController::Base\n  include Pundit::Authorization\nend\n```\n\nOptionally, you can run the generator, which will set up an application policy\nwith some useful defaults for you:\n\n``` sh\nrails g pundit:install\n```\n\nAfter generating your application policy, restart the Rails server so that Rails\ncan pick up any classes in the new `app/policies/` directory.\n\n## Policies\n\nPundit is focused around the notion of policy classes. We suggest that you put\nthese classes in `app/policies`. This is an example that allows updating a post\nif the user is an admin, or if the post is unpublished:\n\n``` ruby\nclass PostPolicy\n  attr_reader :user, :post\n\n  def initialize(user, post)\n    @user = user\n    @post = post\n  end\n\n  def update?\n    user.admin? || !post.published?\n  end\nend\n```\n\nAs you can see, this is a plain Ruby class. Pundit makes the following\nassumptions about this class:\n\n- The class has the same name as some kind of model class, only suffixed\n  with the word \"Policy\".\n- The first argument is a user. In your controller, Pundit will call the\n  `current_user` method to retrieve what to send into this argument\n- The second argument is some kind of model object, whose authorization\n  you want to check. This does not need to be an ActiveRecord or even\n  an ActiveModel object, it can be anything really.\n- The class implements some kind of query method, in this case `update?`.\n  Usually, this will map to the name of a particular controller action.\n\nThat's it really.\n\nUsually you'll want to inherit from the application policy created by the\ngenerator, or set up your own base class to inherit from:\n\n``` ruby\nclass PostPolicy < ApplicationPolicy\n  def update?\n    user.admin? or not record.published?\n  end\nend\n```\n\nIn the generated `ApplicationPolicy`, the model object is called `record`.\n\nSupposing that you have an instance of class `Post`, Pundit now lets you do\nthis in your controller:\n\n``` ruby\ndef update\n  @post = Post.find(params[:id])\n  authorize @post\n  if @post.update(post_params)\n    redirect_to @post\n  else\n    render :edit\n  end\nend\n```\n\nThe authorize method automatically infers that `Post` will have a matching\n`PostPolicy` class, and instantiates this class, handing in the current user\nand the given record. It then infers from the action name, that it should call\n`update?` on this instance of the policy. In this case, you can imagine that\n`authorize` would have done something like this:\n\n``` ruby\nunless PostPolicy.new(current_user, @post).update?\n  raise Pundit::NotAuthorizedError, \"not allowed to PostPolicy#update? this Post\"\nend\n```\n\nYou can pass a second argument to `authorize` if the name of the permission you\nwant to check doesn't match the action name. For example:\n\n``` ruby\ndef publish\n  @post = Post.find(params[:id])\n  authorize @post, :update?\n  @post.publish!\n  redirect_to @post\nend\n```\n\nYou can pass an argument to override the policy class if necessary. For example:\n\n```ruby\ndef create\n  @publication = find_publication # assume this method returns any model that behaves like a publication\n  # @publication.class => Post\n  authorize @publication, policy_class: PublicationPolicy\n  @publication.publish!\n  redirect_to @publication\nend\n```\n\nIf you don't have an instance for the first argument to `authorize`, then you can pass\nthe class. For example:\n\nPolicy:\n```ruby\nclass PostPolicy < ApplicationPolicy\n  def admin_list?\n    user.admin?\n  end\nend\n```\n\nController:\n```ruby\ndef admin_list\n  authorize Post # we don't have a particular post to authorize\n  # Rest of controller action\nend\n```\n\n`authorize` returns the instance passed to it, so you can chain it like this:\n\nController:\n```ruby\ndef show\n  @user = authorize User.find(params[:id])\nend\n```\n\nYou can easily get a hold of an instance of the policy through the `policy`\nmethod in both the view and controller. This is especially useful for\nconditionally showing links or buttons in the view:\n\n``` erb\n<% if policy(@post).update? %>\n  <%= link_to \"Edit post\", edit_post_path(@post) %>\n<% end %>\n```\n## Headless policies\n\nGiven there is a policy without a corresponding model / ruby class,\nyou can retrieve it by passing a symbol.\n\n```ruby\n# app/policies/dashboard_policy.rb\nclass DashboardPolicy\n  attr_reader :user\n\n  # `_record` in this example will be :dashboard\n  def initialize(user, _record)\n    @user = user\n  end\n\n  def show?\n    user.admin?\n  end\nend\n```\n\nNote that the headless policy still needs to accept two arguments. The\nsecond argument will be the symbol `:dashboard` in this case, which\nis what is passed as the record to `authorize` below.\n\n```ruby\n# In controllers\ndef show\n  authorize :dashboard, :show?\n  ...\nend\n```\n\n```erb\n# In views\n<% if policy(:dashboard).show? %>\n  <%= link_to 'Dashboard', dashboard_path %>\n<% end %>\n```\n\n## Scopes\n\nOften, you will want to have some kind of view listing records which a\nparticular user has access to. When using Pundit, you are expected to\ndefine a class called a policy scope. It can look something like this:\n\n``` ruby\nclass PostPolicy < ApplicationPolicy\n  class Scope\n    def initialize(user, scope)\n      @user  = user\n      @scope = scope\n    end\n\n    def resolve\n      if user.admin?\n        scope.all\n      else\n        scope.where(published: true)\n      end\n    end\n\n    private\n\n    attr_reader :user, :scope\n  end\n\n  def update?\n    user.admin? or not record.published?\n  end\nend\n```\n\nPundit makes the following assumptions about this class:\n\n- The class has the name `Scope` and is nested under the policy class.\n- The first argument is a user. In your controller, Pundit will call the\n  `current_user` method to retrieve what to send into this argument.\n- The second argument is a scope of some kind on which to perform some kind of\n  query. It will usually be an ActiveRecord class or a\n  `ActiveRecord::Relation`, but it could be something else entirely.\n- Instances of this class respond to the method `resolve`, which should return\n  some kind of result which can be iterated over. For ActiveRecord classes,\n  this would usually be an `ActiveRecord::Relation`.\n\nYou'll probably want to inherit from the application policy scope generated by the\ngenerator, or create your own base class to inherit from:\n\n``` ruby\nclass PostPolicy < ApplicationPolicy\n  class Scope < ApplicationPolicy::Scope\n    def resolve\n      if user.admin?\n        scope.all\n      else\n        scope.where(published: true)\n      end\n    end\n  end\n\n  def update?\n    user.admin? or not record.published?\n  end\nend\n```\n\nYou can now use this class from your controller via the `policy_scope` method:\n\n``` ruby\ndef index\n  @posts = policy_scope(Post)\nend\n\ndef show\n  @post = policy_scope(Post).find(params[:id])\nend\n```\n\nLike with the authorize method, you can also override the policy scope class:\n\n``` ruby\ndef index\n  # publication_class => Post\n  @publications = policy_scope(publication_class, policy_scope_class: PublicationPolicy::Scope)\nend\n```\n\nIn this case it is a shortcut for doing:\n\n``` ruby\ndef index\n  @publications = PublicationPolicy::Scope.new(current_user, Post).resolve\nend\n```\n\nYou can, and are encouraged to, use this method in views:\n\n``` erb\n<% policy_scope(@user.posts).each do |post| %>\n  <p><%= link_to post.title, post_path(post) %></p>\n<% end %>\n```\n\n## Ensuring policies and scopes are used\n\nWhen you are developing an application with Pundit it can be easy to forget to\nauthorize some action. People are forgetful after all. Since Pundit encourages\nyou to add the `authorize` call manually to each controller action, it's really\neasy to miss one.\n\nThankfully, Pundit has a handy feature which reminds you in case you forget.\nPundit tracks whether you have called `authorize` anywhere in your controller\naction. Pundit also adds a method to your controllers called\n`verify_authorized`. This method will raise an exception if `authorize` has not\nyet been called. You should run this method in an `after_action` hook to ensure\nthat you haven't forgotten to authorize the action. For example:\n\n``` ruby\nclass ApplicationController < ActionController::Base\n  include Pundit::Authorization\n  after_action :verify_authorized\nend\n```\n\nLikewise, Pundit also adds `verify_policy_scoped` to your controller. This\nwill raise an exception similar to `verify_authorized`. However, it tracks\nif `policy_scope` is used instead of `authorize`. This is mostly useful for\ncontroller actions like `index` which find collections with a scope and don't\nauthorize individual instances.\n\n``` ruby\nclass ApplicationController < ActionController::Base\n  include Pundit::Authorization\n  after_action :verify_pundit_authorization\n\n  def verify_pundit_authorization\n    if action_name == \"index\"\n      verify_policy_scoped\n    else\n      verify_authorized\n    end\n  end\nend\n```\n\n**This verification mechanism only exists to aid you while developing your\napplication, so you don't forget to call `authorize`. It is not some kind of\nfailsafe mechanism or authorization mechanism. You should be able to remove\nthese filters without affecting how your app works in any way.**\n\nSome people have found this feature confusing, while many others\nfind it extremely helpful. If you fall into the category of people who find it\nconfusing then you do not need to use it. Pundit will work fine without\nusing `verify_authorized` and `verify_policy_scoped`.\n\n### Conditional verification\n\nIf you're using `verify_authorized` in your controllers but need to\nconditionally bypass verification, you can use `skip_authorization`. For\nbypassing `verify_policy_scoped`, use `skip_policy_scope`. These are useful\nin circumstances where you don't want to disable verification for the\nentire action, but have some cases where you intend to not authorize.\n\n```ruby\ndef show\n  record = Record.find_by(attribute: \"value\")\n  if record.present?\n    authorize record\n  else\n    skip_authorization\n  end\nend\n```\n\n## Manually specifying policy classes\n\nSometimes you might want to explicitly declare which policy to use for a given\nclass, instead of letting Pundit infer it. This can be done like so:\n\n``` ruby\nclass Post\n  def self.policy_class\n    PostablePolicy\n  end\nend\n```\n\nAlternatively, you can declare an instance method:\n\n``` ruby\nclass Post\n  def policy_class\n    PostablePolicy\n  end\nend\n```\n\n## Plain old Ruby\n\nPundit is a very small library on purpose, and it doesn't do anything you can't do yourself. There's no secret sauce here. It does as little as possible, and then gets out of your way.\n\nWith the few but powerful helpers available in Pundit, you have the power to build a well structured, fully working authorization system without using any special DSLs or funky syntax.\n\nRemember that all of the policy and scope classes are plain Ruby classes, which means you can use the same mechanisms you always use to DRY things up. Encapsulate a set of permissions into a module and include them in multiple policies. Use `alias_method` to make some permissions behave the same as others. Inherit from a base set of permissions. Use metaprogramming if you really have to.\n\n## Generator\n\nUse the supplied generator to generate policies:\n\n``` sh\nrails g pundit:policy post\n```\n\n## Closed systems\n\nIn many applications, only logged in users are really able to do anything. If\nyou're building such a system, it can be kind of cumbersome to check that the\nuser in a policy isn't `nil` for every single permission. Aside from policies,\nyou can add this check to the base class for scopes.\n\nWe suggest that you define a filter that redirects unauthenticated users to the\nlogin page. As a secondary defence, if you've defined an ApplicationPolicy, it\nmight be a good idea to raise an exception if somehow an unauthenticated user\ngot through. This way you can fail more gracefully.\n\n``` ruby\nclass ApplicationPolicy\n  def initialize(user, record)\n    raise Pundit::NotAuthorizedError, \"must be logged in\" unless user\n    @user   = user\n    @record = record\n  end\n\n  class Scope\n    attr_reader :user, :scope\n\n    def initialize(user, scope)\n      raise Pundit::NotAuthorizedError, \"must be logged in\" unless user\n      @user = user\n      @scope = scope\n    end\n  end\nend\n```\n\n## NilClassPolicy\n\nTo support a [null object pattern](https://en.wikipedia.org/wiki/Null_Object_pattern)\nyou may find that you want to implement a `NilClassPolicy`. This might be useful\nwhere you want to extend your ApplicationPolicy to allow some tolerance of, for\nexample, associations which might be `nil`.\n\n```ruby\nclass NilClassPolicy < ApplicationPolicy\n  class Scope < ApplicationPolicy::Scope\n    def resolve\n      raise Pundit::NotDefinedError, \"Cannot scope NilClass\"\n    end\n  end\n\n  def show?\n    false # Nobody can see nothing\n  end\nend\n```\n\n## Rescuing a denied Authorization in Rails\n\nPundit raises a `Pundit::NotAuthorizedError` you can\n[rescue_from](https://guides.rubyonrails.org/action_controller_overview.html#rescue-from)\nin your `ApplicationController`. You can customize the `user_not_authorized`\nmethod in every controller.\n\n```ruby\nclass ApplicationController < ActionController::Base\n  include Pundit::Authorization\n\n  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized\n\n  private\n\n  def user_not_authorized\n    flash[:alert] = \"You are not authorized to perform this action.\"\n    redirect_back_or_to(root_path)\n  end\nend\n```\n\nAlternatively, you can globally handle Pundit::NotAuthorizedError's by having rails handle them as a 403 error and serving a 403 error page. Add the following to application.rb:\n\n```config.action_dispatch.rescue_responses[\"Pundit::NotAuthorizedError\"] = :forbidden```\n\n## Creating custom error messages\n\n`NotAuthorizedError`s provide information on what query (e.g. `:create?`), what\nrecord (e.g. an instance of `Post`), and what policy (e.g. an instance of\n`PostPolicy`) caused the error to be raised.\n\nOne way to use these `query`, `record`, and `policy` properties is to connect\nthem with `I18n` to generate error messages. Here's how you might go about doing\nthat.\n\n```ruby\nclass ApplicationController < ActionController::Base\n rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized\n\n private\n\n def user_not_authorized(exception)\n   policy_name = exception.policy.class.to_s.underscore\n\n   flash[:error] = t \"#{policy_name}.#{exception.query}\", scope: \"pundit\", default: :default\n   redirect_back_or_to(root_path)\n end\nend\n```\n\n```yaml\nen:\n pundit:\n   default: 'You cannot perform this action.'\n   post_policy:\n     update?: 'You cannot edit this post!'\n     create?: 'You cannot create posts!'\n```\n\nThis is an example. Pundit is agnostic as to how you implement your error messaging.\n\n## Manually retrieving policies and scopes\n\nSometimes you want to retrieve a policy for a record outside the controller or\nview. For example when you delegate permissions from one policy to another.\n\nYou can easily retrieve policies and scopes like this:\n\n``` ruby\nPundit.policy!(user, post)\nPundit.policy(user, post)\n\nPundit.policy_scope!(user, Post)\nPundit.policy_scope(user, Post)\n```\n\nThe bang methods will raise an exception if the policy does not exist, whereas\nthose without the bang will return nil.\n\n## Customize Pundit user\n\nOn occasion, your controller may be unable to access `current_user`, or the method that should be invoked by Pundit may not be `current_user`. To address this, you can define a method in your controller named `pundit_user`.\n\n```ruby\ndef pundit_user\n  User.find_by_other_means\nend\n```\n\nFor instance, Rails 8 includes a built-in [authentication generator](https://github.com/rails/rails/tree/8-0-stable/railties/lib/rails/generators/rails/authentication). If you choose to use it, the currently logged-in user is accessed via `Current.user` instead of `current_user`.\n\nTo ensure compatibility with Pundit, define a `pundit_user` method in `application_controller.rb` (or another suitable location) as follows:\n\n```ruby\ndef pundit_user\n  Current.user\nend\n```\n\n### Handling User Switching in Pundit\n\nWhen switching users in your application, it's important to reset the Pundit user context to ensure that authorization policies are applied correctly for the new user. Pundit caches the user context, so failing to reset it could result in incorrect permissions being applied.\n\nTo handle user switching, you can use the following pattern in your controller:\n\n```ruby\nclass ApplicationController\n  include Pundit::Authorization\n\n  def switch_user_to(user)\n    terminate_session if authenticated?\n    start_new_session_for user\n    pundit_reset!\n  end\nend\n```\n\nMake sure to invoke `pundit_reset!` whenever changing the user. This ensures the cached authorization context is reset, preventing any incorrect permissions from being applied.\n\n## Policy Namespacing\n\nIn some cases it might be helpful to have multiple policies that serve different contexts for a resource. A prime example of this is the case where User policies differ from Admin policies. To authorize with a namespaced policy, pass the namespace into the `authorize` helper in an array:\n\n```ruby\nauthorize(post)                   # => will look for a PostPolicy\nauthorize([:admin, post])         # => will look for an Admin::PostPolicy\nauthorize([:foo, :bar, post])     # => will look for a Foo::Bar::PostPolicy\n\npolicy_scope(Post)                # => will look for a PostPolicy::Scope\npolicy_scope([:admin, Post])      # => will look for an Admin::PostPolicy::Scope\npolicy_scope([:foo, :bar, Post])  # => will look for a Foo::Bar::PostPolicy::Scope\n```\n\nIf you are using namespaced policies for something like Admin areas, we recommend defining a `pundit_namespace` hook in your `ApplicationController` and overriding it in namespaced controllers:\n\n```ruby\nclass ApplicationController < ActionController::Base\n  include Pundit::Authorization\n\n  private\n\n  def pundit_namespace(record) = record\n\n  def authorize(record, ...) = super(pundit_namespace(record), ...)\n  def policy_scope(scope, ...) = super(pundit_namespace(scope), ...)\nend\n\nclass AdminController < ApplicationController\n  private\n\n  # Override the pundit namespace in Admin.\n  def pundit_namespace(record) = [:admin, record]\nend\n\nclass Admin::PostController < AdminController\n  def index\n    policy_scope(Post)\n  end\n\n  def show\n    post = authorize Post.find(params[:id])\n  end\nend\n```\n\n## Additional context\n\nPundit strongly encourages you to model your application in such a way that the\nonly context you need for authorization is a user object and a domain model that\nyou want to check authorization for. If you find yourself needing more context than\nthat, consider whether you are authorizing the right domain model, maybe another\ndomain model (or a wrapper around multiple domain models) can provide the context\nyou need.\n\nPundit does not allow you to pass additional arguments to policies for precisely\nthis reason.\n\nHowever, in very rare cases, you might need to authorize based on more context than just\nthe currently authenticated user. Suppose for example that authorization is dependent\non IP address in addition to the authenticated user. In that case, one option is to\ncreate a special class which wraps up both user and IP and passes it to the policy.\n\n``` ruby\nclass UserContext < Data.define(:user, :ip)\nend\n\nclass ApplicationController\n  include Pundit::Authorization\n\n  def pundit_user = UserContext.new(current_user, request.ip)\nend\n```\n\n## Strong parameters\n\nIn Rails, [mass-assignment protection is handled in the controller](https://guides.rubyonrails.org/action_controller_overview.html#strong-parameters). With Pundit you can control which attributes a user has access to update via your policies. You can set up an `expected_attributes_for_action(action_name)` method in your policy like this:\n\n```ruby\n# app/policies/post_policy.rb\nclass PostPolicy < ApplicationPolicy\n  def expected_attributes_for_action(_action_name)\n    if user.admin? || user.owner_of?(post)\n      [:title, :body, :tag_list]\n    else\n      [:tag_list]\n    end\n  end\nend\n```\n\nYou can now retrieve these attributes from the policy:\n\n```ruby\n# app/controllers/posts_controller.rb\nclass PostsController < ApplicationController\n  def update\n    @post = Post.find(params[:id])\n    if @post.update(post_params)\n      redirect_to @post\n    else\n      render :edit\n    end\n  end\n\n  private\n\n  def post_params\n    params.expect(policy(@post).expected_attributes_for_action(action_name))\n  end\nend\n```\n\nHowever, this is a bit cumbersome, so Pundit provides a convenient helper method with `#expected_attributes`:\n\n```ruby\n# app/controllers/posts_controller.rb\nclass PostsController < ApplicationController\n  def update\n    @post = Post.find(params[:id])\n    if @post.update(expected_attributes(@post))\n      redirect_to @post\n    else\n      render :edit\n    end\n  end\nend\n```\n\n### Permitted Parameters\n\nPundit still support the old `params.require.permit()` style of permitting attributes, although `params.expect()` is preferred.\n\nIf you need to fetch parameters based on namespaces different from the suggested one, override the below method, in your controller, and return an instance of `ActionController::Parameters`.\n\n```ruby\ndef pundit_params_for(record)\n  params.require(pundit_param_key(record))\nend\n```\n\nFor example:\n\n```ruby\n# If you don't want to use require\ndef pundit_params_for(record)\n  params.fetch(pundit_param_key(record), {})\nend\n\n# If you are using something like the JSON API spec\ndef pundit_params_for(_record)\n  params.fetch(:data, {}).fetch(:attributes, {})\nend\n```\n\n## RSpec\n\n### Policy Specs\n\n> [!TIP]\n> An alternative approach to Pundit policy specs is scoping them to a user context as outlined in this\n[excellent post](https://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/) and implemented in the third party [pundit-matchers](https://github.com/punditcommunity/pundit-matchers) gem.\n\nPundit includes a mini-DSL for writing expressive tests for your policies in RSpec.\nRequire `pundit/rspec` in your `spec_helper.rb`:\n\n``` ruby\nrequire \"pundit/rspec\"\n```\n\nThen put your policy specs in `spec/policies`, and make them look somewhat like this:\n\n``` ruby\ndescribe PostPolicy do\n  subject { described_class }\n\n  permissions :update?, :edit? do\n    it \"denies access if post is published\" do\n      expect(subject).not_to permit(User.new(admin: false), Post.new(published: true))\n    end\n\n    it \"grants access if post is published and user is an admin\" do\n      expect(subject).to permit(User.new(admin: true), Post.new(published: true))\n    end\n\n    it \"grants access if post is unpublished\" do\n      expect(subject).to permit(User.new(admin: false), Post.new(published: false))\n    end\n  end\nend\n```\n\n### Custom matcher description\n\nBy default rspec includes an inspected `user` and `record` in the matcher description, which might become overly verbose:\n\n```\nPostPolicy\n  update? and show?\n    is expected to permit #<User:0x0000000104aefd80> and #<Post:0x0000000104aef8d0 @user=#<User:0x0000000104aefd80>>\n```\n\nYou can override the default description with a static string, or a block:\n\n```ruby\n# static alternative: Pundit::RSpec::Matchers.description = \"permit the user\"\nPundit::RSpec::Matchers.description = ->(user, record) do\n  \"permit user with role #{user.role} to access record with ID #{record.id}\"\nend\n```\n\nWhich would make for a less chatty output:\n\n```\nPostPolicy\n  update? and show?\n    is expected to permit user with role admin to access record with ID 130\n```\n\n### Focus Support\n\nIf your RSpec config has `filter_run_when_matching :focus`, you may tag the `permissions` helper like so:\n\n```\npermissions :show?, :focus do\n```\n\n### Scope Specs\n\nPundit does not provide a DSL for testing scopes. Test them like you would a regular Ruby class!\n\n### Linting with RuboCop RSpec\n\nWhen you lint your RSpec spec files with `rubocop-rspec`, it will fail to properly detect RSpec constructs that Pundit defines, `permissions`.\nMake sure to use `rubocop-rspec` 2.0 or newer and add the following to your `.rubocop.yml`:\n\n```yaml\ninherit_gem:\n  pundit: config/rubocop-rspec.yml\n```\n\n# External Resources\n\n- [RailsApps Example Application: Pundit and Devise](https://github.com/RailsApps/rails-devise-pundit)\n- [Migrating to Pundit from CanCan](https://blog.carbonfive.com/2013/10/21/migrating-to-pundit-from-cancan/)\n- [Testing Pundit Policies with RSpec](https://thunderboltlabs.com/blog/2013/03/27/testing-pundit-policies-with-rspec/)\n- [Testing Pundit with Minitest](https://github.com/varvet/pundit/issues/204#issuecomment-60166450)\n- [Using Pundit outside of a Rails controller](https://github.com/varvet/pundit/pull/136)\n- [Straightforward Rails Authorization with Pundit](https://www.sitepoint.com/straightforward-rails-authorization-with-pundit/)\n\n## Other implementations\n\n- [Flask-Pundit](https://github.com/anurag90x/flask-pundit) (Python) is a [Flask](https://flask.pocoo.org/) extension \"heavily inspired by\" Pundit\n\n# License\n\nLicensed under the MIT license, see the separate LICENSE.txt file.\n"
  },
  {
    "path": "Rakefile",
    "content": "# frozen_string_literal: true\n\nrequire \"rubygems\"\nrequire \"bundler/gem_tasks\"\nrequire \"rspec/core/rake_task\"\nrequire \"yard\"\nrequire \"rubocop/rake_task\"\n\nRuboCop::RakeTask.new\n\ndesc \"Run all examples\"\nRSpec::Core::RakeTask.new(:spec)\n\nYARD::Rake::YardocTask.new do |t|\n  t.files = [\"lib/**/*.rb\"]\n  t.stats_options = [\"--list-undoc\"]\nend\n\ntask default: :spec\n"
  },
  {
    "path": "SECURITY.md",
    "content": "# Security Policy\n\nPlease do not file an issue on GitHub, or send a PR addressing the issue.\n\n## Supported versions\n\nMost recent major version only.\n\n## Reporting a vulnerability\n\nContact one of the maintainers directly:\n\n* [@Burgestrand](https://github.com/Burgestrand)\n* [@dgmstuart](https://github.com/dgmstuart)\n* [@varvet](https://github.com/varvet)\n\nYou can report vulnerabilities on GitHub too: https://github.com/varvet/pundit/security\n\nThank you!\n"
  },
  {
    "path": "bin/console",
    "content": "#!/usr/bin/env ruby\n# frozen_string_literal: true\n\nrequire \"bundler/setup\"\nrequire \"pundit\"\n\n# You can add fixtures and/or initialization code here to make experimenting\n# with your gem easier. You can also use a different console, if you like.\n\nrequire \"irb\"\nIRB.start(__FILE__)\n"
  },
  {
    "path": "bin/setup",
    "content": "#!/usr/bin/env bash\nset -euo pipefail\nIFS=$'\\n\\t'\nset -vx\n\nbundle install\n\n# Do any other automated setup that you need to do here\n"
  },
  {
    "path": "config/rubocop-rspec.yml",
    "content": "RSpec:\n  Language:\n    ExampleGroups:\n      Regular:\n        - permissions\n"
  },
  {
    "path": "lib/generators/pundit/install/USAGE",
    "content": "Description:\n    Generates an application policy as a starting point for your application.\n"
  },
  {
    "path": "lib/generators/pundit/install/install_generator.rb",
    "content": "# frozen_string_literal: true\n\nmodule Pundit\n  # @private\n  module Generators\n    # @private\n    class InstallGenerator < ::Rails::Generators::Base\n      source_root File.expand_path(\"templates\", __dir__)\n\n      def copy_application_policy\n        template \"application_policy.rb.tt\", \"app/policies/application_policy.rb\"\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/generators/pundit/install/templates/application_policy.rb.tt",
    "content": "# frozen_string_literal: true\n\nclass ApplicationPolicy\n  attr_reader :user, :record\n\n  def initialize(user, record)\n    @user = user\n    @record = record\n  end\n\n  def index?\n    false\n  end\n\n  def show?\n    false\n  end\n\n  def create?\n    false\n  end\n\n  def new?\n    create?\n  end\n\n  def update?\n    false\n  end\n\n  def edit?\n    update?\n  end\n\n  def destroy?\n    false\n  end\n\n  class Scope\n    def initialize(user, scope)\n      @user = user\n      @scope = scope\n    end\n\n    def resolve\n      raise NoMethodError, \"You must define #resolve in #{self.class}\"\n    end\n\n    private\n\n    attr_reader :user, :scope\n  end\nend\n"
  },
  {
    "path": "lib/generators/pundit/policy/USAGE",
    "content": "Description:\n    Generates a policy for a model with the given name.\n\nExample:\n    rails generate pundit:policy user\n\n    This will create:\n        app/policies/user_policy.rb\n"
  },
  {
    "path": "lib/generators/pundit/policy/policy_generator.rb",
    "content": "# frozen_string_literal: true\n\nmodule Pundit\n  # @private\n  module Generators\n    # @private\n    class PolicyGenerator < ::Rails::Generators::NamedBase\n      source_root File.expand_path(\"templates\", __dir__)\n\n      def create_policy\n        template \"policy.rb.tt\", File.join(\"app/policies\", class_path, \"#{file_name}_policy.rb\")\n      end\n\n      hook_for :test_framework\n    end\n  end\nend\n"
  },
  {
    "path": "lib/generators/pundit/policy/templates/policy.rb.tt",
    "content": "<% module_namespacing do -%>\nclass <%= class_name %>Policy < ApplicationPolicy\n  # NOTE: Up to Pundit v2.3.1, the inheritance was declared as\n  # `Scope < Scope` rather than `Scope < ApplicationPolicy::Scope`.\n  # In most cases the behavior will be identical, but if updating existing\n  # code, beware of possible changes to the ancestors:\n  # https://gist.github.com/Burgestrand/4b4bc22f31c8a95c425fc0e30d7ef1f5\n\n  class Scope < ApplicationPolicy::Scope\n    # NOTE: Be explicit about which records you allow access to!\n    # def resolve\n    #   scope.all\n    # end\n  end\nend\n<% end -%>\n"
  },
  {
    "path": "lib/generators/rspec/policy_generator.rb",
    "content": "# frozen_string_literal: true\n\n# @private\nmodule Rspec\n  # @private\n  module Generators\n    # @private\n    class PolicyGenerator < ::Rails::Generators::NamedBase\n      source_root File.expand_path(\"templates\", __dir__)\n\n      def create_policy_spec\n        template \"policy_spec.rb.tt\", File.join(\"spec/policies\", class_path, \"#{file_name}_policy_spec.rb\")\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/generators/rspec/templates/policy_spec.rb.tt",
    "content": "require '<%= File.exist?('spec/rails_helper.rb') ? 'rails_helper' : 'spec_helper' %>'\n\nRSpec.describe <%= class_name %>Policy, type: :policy do\n  let(:user) { User.new }\n\n  subject { described_class }\n\n  permissions \".scope\" do\n    pending \"add some examples to (or delete) #{__FILE__}\"\n  end\n\n  permissions :show? do\n    pending \"add some examples to (or delete) #{__FILE__}\"\n  end\n\n  permissions :create? do\n    pending \"add some examples to (or delete) #{__FILE__}\"\n  end\n\n  permissions :update? do\n    pending \"add some examples to (or delete) #{__FILE__}\"\n  end\n\n  permissions :destroy? do\n    pending \"add some examples to (or delete) #{__FILE__}\"\n  end\nend\n"
  },
  {
    "path": "lib/generators/test_unit/policy_generator.rb",
    "content": "# frozen_string_literal: true\n\n# @private\nmodule TestUnit\n  # @private\n  module Generators\n    # @private\n    class PolicyGenerator < ::Rails::Generators::NamedBase\n      source_root File.expand_path(\"templates\", __dir__)\n\n      def create_policy_test\n        template \"policy_test.rb.tt\", File.join(\"test/policies\", class_path, \"#{file_name}_policy_test.rb\")\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/generators/test_unit/templates/policy_test.rb.tt",
    "content": "require 'test_helper'\n\nclass <%= class_name %>PolicyTest < ActiveSupport::TestCase\n  def test_scope\n  end\n\n  def test_show\n  end\n\n  def test_create\n  end\n\n  def test_update\n  end\n\n  def test_destroy\n  end\nend\n"
  },
  {
    "path": "lib/pundit/authorization.rb",
    "content": "# frozen_string_literal: true\n\nmodule Pundit\n  # Pundit DSL to include in your controllers to provide authorization helpers.\n  #\n  # @example\n  #   class ApplicationController < ActionController::Base\n  #     include Pundit::Authorization\n  #   end\n  # @see #pundit\n  # @api public\n  # @since v2.2.0\n  module Authorization\n    extend ActiveSupport::Concern\n\n    included do\n      helper Helper if respond_to?(:helper)\n      if respond_to?(:helper_method)\n        helper_method :policy\n        helper_method :pundit_policy_scope\n        helper_method :pundit_user\n      end\n    end\n\n    protected\n\n    # An instance of {Pundit::Context} initialized with the current user.\n    #\n    # @note this method is memoized and will return the same instance during the request.\n    # @api public\n    # @return [Pundit::Context]\n    # @see #pundit_user\n    # @see #policies\n    # @since v2.3.2\n    def pundit\n      @pundit ||= Pundit::Context.new(\n        user: pundit_user,\n        policy_cache: Pundit::CacheStore::LegacyStore.new(policies)\n      )\n    end\n\n    # Hook method which allows customizing which user is passed to policies and\n    # scopes initialized by {#authorize}, {#policy} and {#policy_scope}.\n    #\n    # @note Make sure to call `pundit_reset!` if this changes during a request.\n    # @see https://github.com/varvet/pundit#customize-pundit-user\n    # @see #pundit\n    # @see #pundit_reset!\n    # @return [Object] the user object to be used with pundit\n    # @since v0.2.2\n    def pundit_user\n      current_user\n    end\n\n    # Clears the cached Pundit authorization data.\n    #\n    # This method should be called when the pundit_user is changed,\n    # such as during user switching, to ensure that stale authorization\n    # data is not used. Pundit caches authorization policies and scopes\n    # for the pundit_user, so calling this method will reset those\n    # caches and ensure that the next authorization checks are performed\n    # with the correct context for the new pundit_user.\n    #\n    # @return [void]\n    # @since v2.5.0\n    def pundit_reset!\n      @pundit = nil\n      @_pundit_policies = nil\n      @_pundit_policy_scopes = nil\n      @_pundit_policy_authorized = nil\n      @_pundit_policy_scoped = nil\n    end\n\n    # @!group Policies\n\n    # Retrieves the policy for the given record, initializing it with the record\n    # and current user and finally throwing an error if the user is not\n    # authorized to perform the given action.\n    #\n    # @param record [Object, Array] the object we're checking permissions of\n    # @param query [Symbol, String] the predicate method to check on the policy (e.g. `:show?`).\n    #   If omitted then this defaults to the Rails controller action name.\n    # @param policy_class [Class] the policy class we want to force use of\n    # @raise [NotAuthorizedError] if the given query method returned false\n    # @return [record] Always returns the passed object record\n    # @see Pundit::Context#authorize\n    # @see #verify_authorized\n    # @since v0.1.0\n    def authorize(record, query = nil, policy_class: nil)\n      query ||= \"#{action_name}?\"\n\n      @_pundit_policy_authorized = true\n\n      pundit.authorize(record, query: query, policy_class: policy_class)\n    end\n\n    # Allow this action not to perform authorization.\n    #\n    # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used\n    # @return [void]\n    # @see #verify_authorized\n    # @since v1.0.0\n    def skip_authorization\n      @_pundit_policy_authorized = :skipped\n    end\n\n    # @return [Boolean] wether or not authorization has been performed\n    # @see #authorize\n    # @see #skip_authorization\n    # @since v1.0.0\n    def pundit_policy_authorized?\n      !!@_pundit_policy_authorized\n    end\n\n    # Raises an error if authorization has not been performed.\n    #\n    # Usually used as an `after_action` filter to prevent programmer error in\n    # forgetting to call {#authorize} or {#skip_authorization}.\n    #\n    # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used\n    # @raise [AuthorizationNotPerformedError] if authorization has not been performed\n    # @return [void]\n    # @see #authorize\n    # @see #skip_authorization\n    # @since v0.1.0\n    def verify_authorized\n      raise AuthorizationNotPerformedError, self.class unless pundit_policy_authorized?\n    end\n\n    # rubocop:disable Naming/MemoizedInstanceVariableName\n\n    # Cache of policies. You should not rely on this method.\n    #\n    # @api private\n    # @since v1.0.0\n    def policies\n      @_pundit_policies ||= {}\n    end\n\n    # rubocop:enable Naming/MemoizedInstanceVariableName\n\n    # @!endgroup\n\n    # Retrieves the policy for the given record.\n    #\n    # @see https://github.com/varvet/pundit#policies\n    # @param record [Object] the object we're retrieving the policy for\n    # @return [Object] instance of policy class with query methods\n    # @since v0.1.0\n    def policy(record)\n      pundit.policy!(record)\n    end\n\n    # @!group Policy Scopes\n\n    # Retrieves the policy scope for the given record.\n    #\n    # @see https://github.com/varvet/pundit#scopes\n    # @param scope [Object] the object we're retrieving the policy scope for\n    # @param policy_scope_class [#resolve] the policy scope class we want to force use of\n    # @return [#resolve, nil] instance of scope class which can resolve to a scope\n    # @since v0.1.0\n    def policy_scope(scope, policy_scope_class: nil)\n      @_pundit_policy_scoped = true\n      policy_scope_class ? policy_scope_class.new(pundit_user, scope).resolve : pundit_policy_scope(scope)\n    end\n\n    # Allow this action not to perform policy scoping.\n    #\n    # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used\n    # @return [void]\n    # @see #verify_policy_scoped\n    # @since v1.0.0\n    def skip_policy_scope\n      @_pundit_policy_scoped = :skipped\n    end\n\n    # @return [Boolean] wether or not policy scoping has been performed\n    # @see #policy_scope\n    # @see #skip_policy_scope\n    # @since v1.0.0\n    def pundit_policy_scoped?\n      !!@_pundit_policy_scoped\n    end\n\n    # Raises an error if policy scoping has not been performed.\n    #\n    # Usually used as an `after_action` filter to prevent programmer error in\n    # forgetting to call {#policy_scope} or {#skip_policy_scope} in index\n    # actions.\n    #\n    # @see https://github.com/varvet/pundit#ensuring-policies-and-scopes-are-used\n    # @raise [AuthorizationNotPerformedError] if policy scoping has not been performed\n    # @return [void]\n    # @see #policy_scope\n    # @see #skip_policy_scope\n    # @since v0.2.1\n    def verify_policy_scoped\n      raise PolicyScopingNotPerformedError, self.class unless pundit_policy_scoped?\n    end\n\n    # rubocop:disable Naming/MemoizedInstanceVariableName\n\n    # Cache of policy scope. You should not rely on this method.\n    #\n    # @api private\n    # @since v1.0.0\n    def policy_scopes\n      @_pundit_policy_scopes ||= {}\n    end\n\n    # rubocop:enable Naming/MemoizedInstanceVariableName\n\n    # This was added to allow calling `policy_scope!` without flipping the\n    # `pundit_policy_scoped?` flag.\n    #\n    # It's used internally by `policy_scope`, as well as from the views\n    # when they call `policy_scope`. It works because views get their helper\n    # from {Pundit::Helper}.\n    #\n    # @note This also memoizes the instance with `scope` as the key.\n    # @see Pundit::Helper#policy_scope\n    # @api private\n    # @since v1.0.0\n    def pundit_policy_scope(scope)\n      policy_scopes[scope] ||= pundit.policy_scope!(scope)\n    end\n    private :pundit_policy_scope\n\n    # @!endgroup\n\n    # @!group Strong Parameters\n\n    # Retrieves a set of expected attributes from the policy.\n    #\n    # @example\n    #   if @post.update(expected_attributes(@post))\n    #     redirect_to @post\n    #   else\n    #     render :edit\n    #   end\n    #\n    # @see https://github.com/varvet/pundit#strong-parameters\n    # @see https://guides.rubyonrails.org/action_controller_overview.html#expect\n    # @param record [Object] the object we're retrieving expected attributes for\n    # @param action [Symbol, String] the name of the action being performed on the record (e.g. `update`).\n    #   If omitted then this defaults to the Rails controller action name.\n    # @param param_key [String] the key that the record would have in the params hash\n    # @return [Hash{String => Object}] the expected attributes\n    # @since v2.6.0\n    def expected_attributes(record, action: action_name, param_key: pundit_param_key(record))\n      policy = policy(record)\n      params.expect(param_key => policy.expected_attributes_for_action(action))\n    end\n\n    # @note This is provided as a hook for overrides.\n    # @param record [Object]\n    # @return [String] the key that the record would have in the params hash\n    # @since v2.6.0\n    def pundit_param_key(record)\n      PolicyFinder.new(record).param_key\n    end\n\n    # Retrieves a set of permitted attributes from the policy.\n    #\n    # Done by instantiating the policy class for the given record and calling\n    # `permitted_attributes` on it, or `permitted_attributes_for_{action}` if\n    # `action` is defined. It then infers what key the record should have in the\n    # params hash and retrieves the permitted attributes from the params hash\n    # under that key.\n    #\n    # @see https://github.com/varvet/pundit#strong-parameters\n    # @param record [Object] the object we're retrieving permitted attributes for\n    # @param action [Symbol, String] the name of the action being performed on the record (e.g. `update`).\n    #   If omitted then this defaults to the Rails controller action name.\n    # @return [Hash{String => Object}] the permitted attributes\n    # @since v1.0.0\n    def permitted_attributes(record, action = action_name)\n      policy = policy(record)\n      method_name = if policy.respond_to?(\"permitted_attributes_for_#{action}\")\n        \"permitted_attributes_for_#{action}\"\n      else\n        \"permitted_attributes\"\n      end\n      pundit_params_for(record).permit(*policy.public_send(method_name))\n    end\n\n    # Retrieves the params for the given record.\n    #\n    # @param record [Object] the object we're retrieving params for\n    # @return [ActionController::Parameters] the params\n    # @since v2.0.0\n    def pundit_params_for(record)\n      params.require(pundit_param_key(record))\n    end\n\n    # @!endgroup\n  end\nend\n"
  },
  {
    "path": "lib/pundit/cache_store/legacy_store.rb",
    "content": "# frozen_string_literal: true\n\nmodule Pundit\n  module CacheStore\n    # A cache store that uses only the record as a cache key, and ignores the user.\n    #\n    # The original cache mechanism used by Pundit.\n    #\n    # @api private\n    # @since v2.3.2\n    class LegacyStore\n      # @since v2.3.2\n      def initialize(hash = {})\n        @store = hash\n      end\n\n      # A cache store that uses only the record as a cache key, and ignores the user.\n      #\n      # @note `nil` results are not cached.\n      # @since v2.3.2\n      def fetch(user:, record:)\n        _ = user\n        @store[record] ||= yield\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/pundit/cache_store/null_store.rb",
    "content": "# frozen_string_literal: true\n\nmodule Pundit\n  module CacheStore\n    # A cache store that does not cache anything.\n    #\n    # Use `NullStore.instance` to get the singleton instance, it is thread-safe.\n    #\n    # @see Pundit::Context#initialize\n    # @api private\n    # @since v2.3.2\n    class NullStore\n      @instance = new\n\n      class << self\n        # @since v2.3.2\n        # @return [NullStore] the singleton instance\n        attr_reader :instance\n      end\n\n      # Always yields, does not cache anything.\n      # @yield\n      # @return [any] whatever the block returns.\n      # @since v2.3.2\n      def fetch(*, **)\n        yield\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/pundit/cache_store.rb",
    "content": "# frozen_string_literal: true\n\nmodule Pundit\n  # Namespace for cache store implementations.\n  #\n  # Cache stores are used to cache policy lookups, so you get the same policy\n  # instance for the same record.\n  # @since v2.3.2\n  module CacheStore\n    # @!group Cache Store Interface\n\n    # @!method fetch(user:, record:, &block)\n    #   Looks up a stored policy or generate a new one.\n    #\n    #   @since v2.3.2\n    #   @note This is a method template, but the method does not exist in this module.\n    #   @param user [Object]  the user that initiated the action\n    #   @param record [Object] the object being accessed\n    #   @param block [Proc] the block to execute if missing\n    #   @return [Object] the policy\n\n    # @!endgroup\n  end\nend\n"
  },
  {
    "path": "lib/pundit/context.rb",
    "content": "# frozen_string_literal: true\n\nmodule Pundit\n  # {Pundit::Context} is intended to be created once per request and user, and\n  # it is then used to perform authorization checks throughout the request.\n  #\n  # @example Using Sinatra\n  #   helpers do\n  #     def current_user = ...\n  #\n  #     def pundit\n  #       @pundit ||= Pundit::Context.new(user: current_user)\n  #     end\n  #   end\n  #\n  #   get \"/posts/:id\" do |id|\n  #     pundit.authorize(Post.find(id), query: :show?)\n  #   end\n  #\n  # @example Using [Roda](https://roda.jeremyevans.net/index.html)\n  #   route do |r|\n  #     context = Pundit::Context.new(user:)\n  #\n  #     r.get \"posts\", Integer do |id|\n  #       context.authorize(Post.find(id), query: :show?)\n  #     end\n  #   end\n  #\n  # @since v2.3.2\n  class Context\n    # @see Pundit::Authorization#pundit\n    # @param user later passed to policies and scopes\n    # @param policy_cache [#fetch] cache store for policies (see e.g. {CacheStore::NullStore})\n    # @since v2.3.2\n    def initialize(user:, policy_cache: CacheStore::NullStore.instance)\n      @user = user\n      @policy_cache = policy_cache\n    end\n\n    # @api public\n    # @see #initialize\n    # @since v2.3.2\n    attr_reader :user\n\n    # @api private\n    # @see #initialize\n    # @since v2.3.2\n    attr_reader :policy_cache\n\n    # @!group Policies\n\n    # Retrieves the policy for the given record, initializing it with the\n    # record and user and finally throwing an error if the user is not\n    # authorized to perform the given action.\n    #\n    # @param possibly_namespaced_record [Object, Array] the object we're checking permissions of\n    # @param query [Symbol, String] the predicate method to check on the policy (e.g. `:show?`)\n    # @param policy_class [Class] the policy class we want to force use of\n    # @raise [NotAuthorizedError] if the given query method returned false\n    # @return [Object] Always returns the passed object record\n    # @since v2.3.2\n    def authorize(possibly_namespaced_record, query:, policy_class:)\n      record = pundit_model(possibly_namespaced_record)\n      policy = if policy_class\n        policy_class.new(user, record)\n      else\n        policy!(possibly_namespaced_record)\n      end\n\n      raise NotAuthorizedError, query: query, record: record, policy: policy unless policy.public_send(query)\n\n      record\n    end\n\n    # Retrieves the policy for the given record.\n    #\n    # @see https://github.com/varvet/pundit#policies\n    # @param record [Object] the object we're retrieving the policy for\n    # @raise [InvalidConstructorError] if the policy constructor called incorrectly\n    # @return [Object, nil] instance of policy class with query methods\n    # @since v2.3.2\n    def policy(record)\n      cached_find(record, &:policy)\n    end\n\n    # Retrieves the policy for the given record, or raises if not found.\n    #\n    # @see https://github.com/varvet/pundit#policies\n    # @param record [Object] the object we're retrieving the policy for\n    # @raise [NotDefinedError] if the policy cannot be found\n    # @raise [InvalidConstructorError] if the policy constructor called incorrectly\n    # @return [Object] instance of policy class with query methods\n    # @since v2.3.2\n    def policy!(record)\n      cached_find(record, &:policy!)\n    end\n\n    # @!endgroup\n\n    # @!group Scopes\n\n    # Retrieves the policy scope for the given record.\n    #\n    # @see https://github.com/varvet/pundit#scopes\n    # @param scope [Object] the object we're retrieving the policy scope for\n    # @raise [InvalidConstructorError] if the policy constructor called incorrectly\n    # @return [Scope{#resolve}, nil] instance of scope class which can resolve to a scope\n    # @since v2.3.2\n    def policy_scope(scope)\n      policy_scope_class = policy_finder(scope).scope\n      return unless policy_scope_class\n\n      begin\n        policy_scope = policy_scope_class.new(user, pundit_model(scope))\n      rescue ArgumentError\n        raise InvalidConstructorError, \"Invalid #<#{policy_scope_class}> constructor is called\"\n      end\n\n      policy_scope.resolve\n    end\n\n    # Retrieves the policy scope for the given record. Raises if not found.\n    #\n    # @see https://github.com/varvet/pundit#scopes\n    # @param scope [Object] the object we're retrieving the policy scope for\n    # @raise [NotDefinedError] if the policy scope cannot be found\n    # @raise [InvalidConstructorError] if the policy constructor called incorrectly\n    # @return [Scope{#resolve}] instance of scope class which can resolve to a scope\n    # @since v2.3.2\n    def policy_scope!(scope)\n      policy_scope_class = policy_finder(scope).scope!\n\n      begin\n        policy_scope = policy_scope_class.new(user, pundit_model(scope))\n      rescue ArgumentError\n        raise InvalidConstructorError, \"Invalid #<#{policy_scope_class}> constructor is called\"\n      end\n\n      policy_scope.resolve\n    end\n\n    # @!endgroup\n\n    private\n\n    # @!group Private Helpers\n\n    # Finds a cached policy for the given record, or yields to find one.\n    #\n    # @api private\n    # @param record [Object] the object we're retrieving the policy for\n    # @yield a policy finder if no policy was cached\n    # @yieldparam [PolicyFinder] policy_finder\n    # @yieldreturn [#new(user, model)]\n    # @return [Policy, nil] an instantiated policy\n    # @raise [InvalidConstructorError] if policy can't be instantated\n    # @since v2.3.2\n    def cached_find(record)\n      policy_cache.fetch(user: user, record: record) do\n        klass = yield policy_finder(record)\n        next unless klass\n\n        model = pundit_model(record)\n\n        begin\n          klass.new(user, model)\n        rescue ArgumentError\n          raise InvalidConstructorError, \"Invalid #<#{klass}> constructor is called\"\n        end\n      end\n    end\n\n    # Return a policy finder for the given record.\n    #\n    # @api private\n    # @return [PolicyFinder]\n    # @since v2.3.2\n    def policy_finder(record)\n      PolicyFinder.new(record)\n    end\n\n    # Given a possibly namespaced record, return the actual record.\n    #\n    # @api private\n    # @since v2.3.2\n    def pundit_model(record)\n      record.is_a?(Array) ? record.last : record\n    end\n  end\nend\n"
  },
  {
    "path": "lib/pundit/error.rb",
    "content": "# frozen_string_literal: true\n\nmodule Pundit\n  # @api private\n  # @since v1.0.0\n  # To avoid name clashes with common Error naming when mixing in Pundit,\n  # keep it here with compact class style definition.\n  class Error < StandardError; end\n\n  # Error that will be raised when authorization has failed\n  # @since v0.1.0\n  class NotAuthorizedError < Error\n    # @see #initialize\n    # @since v0.2.3\n    attr_reader :query\n    # @see #initialize\n    # @since v0.2.3\n    attr_reader :record\n    # @see #initialize\n    # @since v0.2.3\n    attr_reader :policy\n\n    # @since v1.0.0\n    #\n    # @overload initialize(message)\n    #   Create an error with a simple error message.\n    #   @param [String] message A simple error message string.\n    #\n    # @overload initialize(options)\n    #   Create an error with the specified attributes.\n    #   @param [Hash] options The error options.\n    #   @option options [String] :message Optional custom error message. Will default to a generalized message.\n    #   @option options [Symbol] :query The name of the policy method that was checked.\n    #   @option options [Object] :record The object that was being checked with the policy.\n    #   @option options [Class] :policy The class of policy that was used for the check.\n    def initialize(options = {})\n      if options.is_a? String\n        message = options\n      else\n        @query = options[:query]\n        @record = options[:record]\n        @policy = options[:policy]\n\n        message = options.fetch(:message) do\n          record_name = record.is_a?(Class) ? record.to_s : \"this #{record.class}\"\n          \"not allowed to #{policy.class}##{query} #{record_name}\"\n        end\n      end\n\n      super(message)\n    end\n  end\n\n  # Error that will be raised if a policy or policy scope constructor is not called correctly.\n  # @since v2.0.0\n  class InvalidConstructorError < Error; end\n\n  # Error that will be raised if a controller action has not called the\n  # `authorize` or `skip_authorization` methods.\n  # @since v0.2.3\n  class AuthorizationNotPerformedError < Error; end\n\n  # Error that will be raised if a controller action has not called the\n  # `policy_scope` or `skip_policy_scope` methods.\n  # @since v0.3.0\n  class PolicyScopingNotPerformedError < AuthorizationNotPerformedError; end\n\n  # Error that will be raised if a policy or policy scope is not defined.\n  # @since v0.1.0\n  class NotDefinedError < Error; end\nend\n"
  },
  {
    "path": "lib/pundit/helper.rb",
    "content": "# frozen_string_literal: true\n\nmodule Pundit\n  # Rails view helpers, to allow a slightly different view-specific\n  # implementation of the methods in {Pundit::Authorization}.\n  #\n  # @api private\n  # @since v1.0.0\n  module Helper\n    # @see Pundit::Authorization#pundit_policy_scope\n    # @since v1.0.0\n    def policy_scope(scope)\n      pundit_policy_scope(scope)\n    end\n  end\nend\n"
  },
  {
    "path": "lib/pundit/policy_finder.rb",
    "content": "# frozen_string_literal: true\n\n# String#safe_constantize, String#demodulize, String#underscore, String#camelize\nrequire \"active_support/core_ext/string/inflections\"\n\nmodule Pundit\n  # Finds policy and scope classes for given object.\n  # @since v0.1.0\n  # @api public\n  # @example\n  #   user = User.find(params[:id])\n  #   finder = PolicyFinder.new(user)\n  #   finder.policy #=> UserPolicy\n  #   finder.scope #=> UserPolicy::Scope\n  #\n  class PolicyFinder\n    # A constant applied to the end of the class name to find the policy class.\n    #\n    # @api private\n    # @since v2.5.0\n    SUFFIX = \"Policy\"\n\n    # @see #initialize\n    # @since v0.1.0\n    attr_reader :object\n\n    # @param object [any] the object to find policy and scope classes for\n    # @since v0.1.0\n    def initialize(object)\n      @object = object\n    end\n\n    # @return [nil, Scope{#resolve}] scope class which can resolve to a scope\n    # @see https://github.com/varvet/pundit#scopes\n    # @example\n    #   scope = finder.scope #=> UserPolicy::Scope\n    #   scope.resolve #=> <#ActiveRecord::Relation ...>\n    #\n    # @since v0.1.0\n    def scope\n      \"#{policy}::Scope\".safe_constantize\n    end\n\n    # @return [nil, Class] policy class with query methods\n    # @see https://github.com/varvet/pundit#policies\n    # @example\n    #   policy = finder.policy #=> UserPolicy\n    #   policy.show? #=> true\n    #   policy.update? #=> false\n    #\n    # @since v0.1.0\n    def policy\n      klass = find(object)\n      klass.is_a?(String) ? klass.safe_constantize : klass\n    end\n\n    # @return [Scope{#resolve}] scope class which can resolve to a scope\n    # @raise [NotDefinedError] if scope could not be determined\n    #\n    # @since v0.1.0\n    def scope!\n      scope or raise NotDefinedError, \"unable to find scope `#{find(object)}::Scope` for `#{object.inspect}`\"\n    end\n\n    # @return [Class] policy class with query methods\n    # @raise [NotDefinedError] if policy could not be determined\n    #\n    # @since v0.1.0\n    def policy!\n      policy or raise NotDefinedError, \"unable to find policy `#{find(object)}` for `#{object.inspect}`\"\n    end\n\n    # @return [String] the name of the key this object would have in a params hash\n    #\n    # @since v1.1.0\n    def param_key # rubocop:disable Metrics/AbcSize\n      model = object.is_a?(Array) ? object.last : object\n\n      if model.respond_to?(:model_name)\n        model.model_name.param_key.to_s\n      elsif model.is_a?(Class)\n        model.to_s.demodulize.underscore\n      else\n        model.class.to_s.demodulize.underscore\n      end\n    end\n\n    private\n\n    # Given an object, find the policy class name.\n    #\n    # Uses recursion to handle namespaces.\n    #\n    # @return [String, Class] the policy class, or its name.\n    # @since v0.2.0\n    def find(subject)\n      if subject.is_a?(Array)\n        modules = subject.dup\n        last = modules.pop\n        context = modules.map { |x| find_class_name(x) }.join(\"::\")\n        [context, find(last)].join(\"::\")\n      elsif subject.respond_to?(:policy_class)\n        subject.policy_class\n      elsif subject.class.respond_to?(:policy_class)\n        subject.class.policy_class\n      else\n        klass = find_class_name(subject)\n        \"#{klass}#{SUFFIX}\"\n      end\n    end\n\n    # Given an object, find its' class name.\n    #\n    # - Supports ActiveModel.\n    # - Supports regular classes.\n    # - Supports symbols.\n    # - Supports object instances.\n    #\n    # @return [String, Class] the class, or its name.\n    # @since v1.1.0\n    def find_class_name(subject)\n      if subject.respond_to?(:model_name)\n        subject.model_name\n      elsif subject.class.respond_to?(:model_name)\n        subject.class.model_name\n      elsif subject.is_a?(Class)\n        subject\n      elsif subject.is_a?(Symbol)\n        subject.to_s.camelize\n      else\n        subject.class\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/pundit/railtie.rb",
    "content": "# frozen_string_literal: true\n\nmodule Pundit\n  # @since v2.5.0\n  class Railtie < Rails::Railtie\n    if Rails.version.to_f >= 8.0\n      initializer \"pundit.stats_directories\" do\n        require \"rails/code_statistics\"\n\n        if Rails.root.join(\"app/policies\").directory?\n          Rails::CodeStatistics.register_directory(\"Policies\", \"app/policies\")\n        end\n\n        if Rails.root.join(\"test/policies\").directory?\n          Rails::CodeStatistics.register_directory(\"Policy tests\", \"test/policies\", test_directory: true)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "lib/pundit/rspec.rb",
    "content": "# frozen_string_literal: true\n\nrequire \"pundit\"\n# Array#to_sentence\nrequire \"active_support/core_ext/array/conversions\"\n\nmodule Pundit\n  # Namespace for Pundit's RSpec integration.\n  # @since v0.1.0\n  module RSpec\n    # Namespace for Pundit's RSpec matchers.\n    module Matchers\n      extend ::RSpec::Matchers::DSL\n\n      # @!method description=(description)\n      class << self\n        # Used to build a suitable description for the Pundit `permit` matcher.\n        # @api public\n        # @param value [String, Proc]\n        # @example\n        #   Pundit::RSpec::Matchers.description = ->(user, record) do\n        #     \"permit user with role #{user.role} to access record with ID #{record.id}\"\n        #   end\n        attr_writer :description\n\n        # Used to retrieve a suitable description for the Pundit `permit` matcher.\n        # @api private\n        # @private\n        def description(user, record)\n          return @description.call(user, record) if defined?(@description) && @description.respond_to?(:call)\n\n          @description\n        end\n      end\n\n      # rubocop:disable Metrics/BlockLength\n      matcher :permit do |user, record|\n        match_proc = lambda do |policy|\n          @violating_permissions = permissions.find_all do |permission|\n            !policy.new(user, record).public_send(permission)\n          end\n          @violating_permissions.empty?\n        end\n\n        match_when_negated_proc = lambda do |policy|\n          @violating_permissions = permissions.find_all do |permission|\n            policy.new(user, record).public_send(permission)\n          end\n          @violating_permissions.empty?\n        end\n\n        failure_message_proc = lambda do |policy|\n          \"Expected #{policy} to grant #{permissions.to_sentence} on \" \\\n          \"#{record} but #{@violating_permissions.to_sentence} #{was_or_were} not granted\"\n        end\n\n        failure_message_when_negated_proc = lambda do |policy|\n          \"Expected #{policy} not to grant #{permissions.to_sentence} on \" \\\n          \"#{record} but #{@violating_permissions.to_sentence} #{was_or_were} granted\"\n        end\n\n        def was_or_were\n          if @violating_permissions.count > 1\n            \"were\"\n          else\n            \"was\"\n          end\n        end\n\n        description do\n          Pundit::RSpec::Matchers.description(user, record) || super()\n        end\n\n        if respond_to?(:match_when_negated)\n          match(&match_proc)\n          match_when_negated(&match_when_negated_proc)\n          failure_message(&failure_message_proc)\n          failure_message_when_negated(&failure_message_when_negated_proc)\n        else\n          # :nocov:\n          # Compatibility with RSpec < 3.0, released 2014-06-01.\n          match_for_should(&match_proc)\n          match_for_should_not(&match_when_negated_proc)\n          failure_message_for_should(&failure_message_proc)\n          failure_message_for_should_not(&failure_message_when_negated_proc)\n          # :nocov:\n        end\n\n        if ::RSpec.respond_to?(:current_example)\n          def current_example\n            ::RSpec.current_example\n          end\n        else\n          # :nocov:\n          # Compatibility with RSpec < 3.0, released 2014-06-01.\n          def current_example\n            example\n          end\n          # :nocov:\n        end\n\n        def permissions\n          current_example.metadata.fetch(:permissions) do\n            raise KeyError, <<~ERROR.strip\n              No permissions in example metadata, did you forget to wrap with `permissions :show?, ...`?\n            ERROR\n          end\n        end\n      end\n      # rubocop:enable Metrics/BlockLength\n    end\n\n    # Mixed in to all policy example groups to provide a DSL.\n    module DSL\n      # @example\n      #   describe PostPolicy do\n      #     permissions :show?, :update? do\n      #       it { is_expected.to permit(user, own_post) }\n      #     end\n      #   end\n      #\n      # @example focused example group\n      #   describe PostPolicy do\n      #     permissions :show?, :update?, :focus do\n      #       it { is_expected.to permit(user, own_post) }\n      #     end\n      #   end\n      #\n      # @param list [Symbol, Array<Symbol>] a permission to describe\n      # @return [void]\n      def permissions(*list, &block)\n        metadata = {permissions: list, caller: caller}\n\n        if list.last == :focus\n          list.pop\n          metadata[:focus] = true\n        end\n\n        description = list.to_sentence\n        describe(description, metadata) { instance_eval(&block) }\n      end\n    end\n\n    # Mixed in to all policy example groups.\n    #\n    # @private not useful\n    module PolicyExampleGroup\n      include Pundit::RSpec::Matchers\n\n      def self.included(base)\n        base.metadata[:type] = :policy\n        base.extend Pundit::RSpec::DSL\n        super\n      end\n    end\n  end\nend\n\nRSpec.configure do |config|\n  config.include(Pundit::RSpec::PolicyExampleGroup, file_path: %r{spec/policies})\n  config.include(Pundit::RSpec::PolicyExampleGroup, type: :policy)\nend\n"
  },
  {
    "path": "lib/pundit/version.rb",
    "content": "# frozen_string_literal: true\n\nmodule Pundit\n  # The current version of Pundit.\n  VERSION = \"2.5.2\"\nend\n"
  },
  {
    "path": "lib/pundit.rb",
    "content": "# frozen_string_literal: true\n\nrequire \"active_support\"\n\nrequire \"pundit/version\"\nrequire \"pundit/error\"\nrequire \"pundit/policy_finder\"\nrequire \"pundit/context\"\nrequire \"pundit/authorization\"\nrequire \"pundit/helper\"\nrequire \"pundit/cache_store\"\nrequire \"pundit/cache_store/null_store\"\nrequire \"pundit/cache_store/legacy_store\"\n\n# :nocov:\nrequire \"pundit/railtie\" if defined?(Rails)\n# :nocov:\n\n# Hello? Yes, this is Pundit.\n#\n# @api public\nmodule Pundit\n  # @api private\n  # @since v1.0.0\n  # @deprecated See {Pundit::PolicyFinder}\n  SUFFIX = Pundit::PolicyFinder::SUFFIX\n\n  # @api private\n  # @private\n  # @since v0.1.0\n  module Generators; end\n\n  def self.included(base)\n    location = caller_locations(1, 1).first\n    warn <<~WARNING\n      'include Pundit' is deprecated. Please use 'include Pundit::Authorization' instead.\n       (called from #{location.label} at #{location.path}:#{location.lineno})\n    WARNING\n    base.include Authorization\n  end\n\n  class << self\n    # @see Pundit::Context#authorize\n    # @since v1.0.0\n    def authorize(user, record, query, policy_class: nil, cache: nil)\n      context = if cache\n        policy_cache = CacheStore::LegacyStore.new(cache)\n        Context.new(user: user, policy_cache: policy_cache)\n      else\n        Context.new(user: user)\n      end\n\n      context.authorize(record, query: query, policy_class: policy_class)\n    end\n\n    # @see Pundit::Context#policy_scope\n    # @since v0.1.0\n    def policy_scope(user, *args, **kwargs, &block)\n      Context.new(user: user).policy_scope(*args, **kwargs, &block)\n    end\n\n    # @see Pundit::Context#policy_scope!\n    # @since v0.1.0\n    def policy_scope!(user, *args, **kwargs, &block)\n      Context.new(user: user).policy_scope!(*args, **kwargs, &block)\n    end\n\n    # @see Pundit::Context#policy\n    # @since v0.1.0\n    def policy(user, *args, **kwargs, &block)\n      Context.new(user: user).policy(*args, **kwargs, &block)\n    end\n\n    # @see Pundit::Context#policy!\n    # @since v0.1.0\n    def policy!(user, *args, **kwargs, &block)\n      Context.new(user: user).policy!(*args, **kwargs, &block)\n    end\n  end\nend\n"
  },
  {
    "path": "pundit.gemspec",
    "content": "# frozen_string_literal: true\n\nrequire_relative \"lib/pundit/version\"\n\nGem::Specification.new do |gem|\n  gem.name = \"pundit\"\n  gem.version = Pundit::VERSION\n  gem.authors = [\"Jonas Nicklas\", \"Varvet AB\"]\n  gem.email = [\"jonas.nicklas@gmail.com\", \"info@varvet.com\"]\n  gem.description = \"Object oriented authorization for Rails applications\"\n  gem.summary = \"OO authorization for Rails\"\n  gem.homepage = \"https://github.com/varvet/pundit\"\n  gem.license = \"MIT\"\n\n  Dir.chdir(__dir__) do\n    gem.files = `git ls-files -z`.split(\"\\x0\").select do |f|\n      f.start_with?(\"lib/\", \"README\", \"SECURITY\", \"LICENSE\", \"CHANGELOG\", \"CONTRIBUTING\", \"config/rubocop-rspec.yml\")\n    end\n  end\n  gem.require_paths = [\"lib\"]\n\n  gem.metadata = {\n    \"rubygems_mfa_required\" => \"true\",\n    \"bug_tracker_uri\" => \"https://github.com/varvet/pundit/issues\",\n    \"changelog_uri\" => \"https://github.com/varvet/pundit/blob/main/CHANGELOG.md\",\n    \"documentation_uri\" => \"https://github.com/varvet/pundit/blob/main/README.md\",\n    \"homepage_uri\" => \"https://github.com/varvet/pundit\",\n    \"source_code_uri\" => \"https://github.com/varvet/pundit\"\n  }\n\n  gem.add_dependency \"activesupport\", \">= 3.0.0\"\nend\n"
  },
  {
    "path": "spec/authorization_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire \"spec_helper\"\nrequire \"action_controller\"\n\nRSpec.describe Pundit::Authorization do\n  def to_params(*args, **kwargs, &block)\n    ActionController::Parameters.new(*args, **kwargs, &block)\n  end\n\n  let(:controller) { Controller.new(user, \"update\", to_params({})) }\n  let(:user) { double(\"user\") }\n  let(:post) { Post.new(user) }\n  let(:comment) { Comment.new }\n  let(:article) { Article.new }\n  let(:article_tag) { ArticleTag.new }\n  let(:wiki) { Wiki.new }\n\n  describe \"#verify_authorized\" do\n    it \"does nothing when authorized\" do\n      controller.authorize(post)\n      controller.verify_authorized\n    end\n\n    it \"raises an exception when not authorized\" do\n      expect { controller.verify_authorized }.to raise_error(Pundit::AuthorizationNotPerformedError)\n    end\n  end\n\n  describe \"#verify_policy_scoped\" do\n    it \"does nothing when policy_scope is used\" do\n      controller.policy_scope(Post)\n      controller.verify_policy_scoped\n    end\n\n    it \"raises an exception when policy_scope is not used\" do\n      expect { controller.verify_policy_scoped }.to raise_error(Pundit::PolicyScopingNotPerformedError)\n    end\n  end\n\n  describe \"#pundit_policy_authorized?\" do\n    it \"is true when authorized\" do\n      controller.authorize(post)\n      expect(controller.pundit_policy_authorized?).to be true\n    end\n\n    it \"is false when not authorized\" do\n      expect(controller.pundit_policy_authorized?).to be false\n    end\n  end\n\n  describe \"#pundit_policy_scoped?\" do\n    it \"is true when policy_scope is used\" do\n      controller.policy_scope(Post)\n      expect(controller.pundit_policy_scoped?).to be true\n    end\n\n    it \"is false when policy scope is not used\" do\n      expect(controller.pundit_policy_scoped?).to be false\n    end\n  end\n\n  describe \"#authorize\" do\n    it \"infers the policy name and authorizes based on it\" do\n      expect(controller.authorize(post)).to be_truthy\n    end\n\n    it \"returns the record on successful authorization\" do\n      expect(controller.authorize(post)).to eq(post)\n    end\n\n    it \"returns the record when passed record with namespace \" do\n      expect(controller.authorize([:project, comment], :update?)).to eq(comment)\n    end\n\n    it \"returns the record when passed record with nested namespace \" do\n      expect(controller.authorize([:project, :admin, comment], :update?)).to eq(comment)\n    end\n\n    it \"returns the policy name symbol when passed record with headless policy\" do\n      expect(controller.authorize(:publication, :create?)).to eq(:publication)\n    end\n\n    it \"returns the class when passed record not a particular instance\" do\n      expect(controller.authorize(Post, :show?)).to eq(Post)\n    end\n\n    it \"can be given a different permission to check\" do\n      expect(controller.authorize(post, :show?)).to be_truthy\n      expect { controller.authorize(post, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)\n    end\n\n    it \"can be given a different policy class\" do\n      expect(controller.authorize(post, :create?, policy_class: PublicationPolicy)).to be_truthy\n    end\n\n    it \"works with anonymous class policies\" do\n      expect(controller.authorize(article_tag, :show?)).to be_truthy\n      expect { controller.authorize(article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)\n    end\n\n    it \"throws an exception when the permission check fails\" do\n      expect { controller.authorize(Post.new) }.to raise_error(Pundit::NotAuthorizedError)\n    end\n\n    it \"throws an exception when a policy cannot be found\" do\n      expect { controller.authorize(Article) }.to raise_error(Pundit::NotDefinedError)\n    end\n\n    it \"caches the policy\" do\n      expect(controller.policies[post]).to be_nil\n      controller.authorize(post)\n      expect(controller.policies[post]).not_to be_nil\n    end\n\n    it \"raises an error when the given record is nil\" do\n      expect { controller.authorize(nil, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)\n    end\n\n    it \"raises an error with a invalid policy constructor\" do\n      expect { controller.authorize(wiki, :destroy?) }.to raise_error(Pundit::InvalidConstructorError)\n    end\n  end\n\n  describe \"#skip_authorization\" do\n    it \"disables authorization verification\" do\n      controller.skip_authorization\n      expect { controller.verify_authorized }.not_to raise_error\n    end\n  end\n\n  describe \"#skip_policy_scope\" do\n    it \"disables policy scope verification\" do\n      controller.skip_policy_scope\n      expect { controller.verify_policy_scoped }.not_to raise_error\n    end\n  end\n\n  describe \"#pundit_user\" do\n    it \"returns the same thing as current_user\" do\n      expect(controller.pundit_user).to eq controller.current_user\n    end\n  end\n\n  describe \"#policy\" do\n    it \"returns an instantiated policy\" do\n      policy = controller.policy(post)\n      expect(policy.user).to eq user\n      expect(policy.post).to eq post\n    end\n\n    it \"throws an exception if the given policy can't be found\" do\n      expect { controller.policy(article) }.to raise_error(Pundit::NotDefinedError)\n    end\n\n    it \"raises an error with a invalid policy constructor\" do\n      expect { controller.policy(wiki) }.to raise_error(Pundit::InvalidConstructorError)\n    end\n\n    it \"allows policy to be injected\" do\n      new_policy = double\n      controller.policies[post] = new_policy\n\n      expect(controller.policy(post)).to eq new_policy\n    end\n  end\n\n  describe \"#policy_scope\" do\n    it \"returns an instantiated policy scope\" do\n      expect(controller.policy_scope(Post)).to eq :published\n    end\n\n    it \"allows policy scope class to be overridden\" do\n      expect(controller.policy_scope(Post, policy_scope_class: PublicationPolicy::Scope)).to eq :published\n    end\n\n    it \"throws an exception if the given policy can't be found\" do\n      expect { controller.policy_scope(Article) }.to raise_error(Pundit::NotDefinedError)\n    end\n\n    it \"raises an error with a invalid policy scope constructor\" do\n      expect { controller.policy_scope(Wiki) }.to raise_error(Pundit::InvalidConstructorError)\n    end\n\n    it \"allows policy_scope to be injected\" do\n      new_scope = double\n      controller.policy_scopes[Post] = new_scope\n\n      expect(controller.policy_scope(Post)).to eq new_scope\n    end\n  end\n\n  describe \"#permitted_attributes\" do\n    it \"checks policy for permitted attributes\" do\n      params = to_params(\n        post: {\n          title: \"Hello\",\n          votes: 5,\n          admin: true\n        }\n      )\n\n      action = \"update\"\n\n      expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq(\n        \"title\" => \"Hello\",\n        \"votes\" => 5\n      )\n      expect(Controller.new(double, action, params).permitted_attributes(post).to_h).to eq(\"votes\" => 5)\n    end\n\n    it \"checks policy for permitted attributes for record of a ActiveModel type\" do\n      customer_post = Customer::Post.new(user)\n      params = to_params(\n        customer_post: {\n          title: \"Hello\",\n          votes: 5,\n          admin: true\n        }\n      )\n\n      action = \"update\"\n\n      expect(Controller.new(user, action, params).permitted_attributes(customer_post).to_h).to eq(\n        \"title\" => \"Hello\",\n        \"votes\" => 5\n      )\n      expect(Controller.new(double, action, params).permitted_attributes(customer_post).to_h).to eq(\n        \"votes\" => 5\n      )\n    end\n\n    it \"goes through the policy cache\" do\n      params = to_params(post: {title: \"Hello\"})\n      user = double\n      post = Post.new(user)\n      controller = Controller.new(user, \"update\", params)\n\n      expect do\n        expect(controller.permitted_attributes(post)).to be_truthy\n        expect(controller.permitted_attributes(post)).to be_truthy\n      end.to change { PostPolicy.instances }.by(1)\n    end\n  end\n\n  describe \"#permitted_attributes_for_action\" do\n    it \"is checked if it is defined in the policy\" do\n      params = to_params(\n        post: {\n          title: \"Hello\",\n          body: \"blah\",\n          votes: 5,\n          admin: true\n        }\n      )\n\n      action = \"revise\"\n      expect(Controller.new(user, action, params).permitted_attributes(post).to_h).to eq(\"body\" => \"blah\")\n    end\n\n    it \"can be explicitly set\" do\n      params = to_params(\n        post: {\n          title: \"Hello\",\n          body: \"blah\",\n          votes: 5,\n          admin: true\n        }\n      )\n\n      action = \"update\"\n      expect(Controller.new(user, action, params).permitted_attributes(post, :revise).to_h).to eq(\"body\" => \"blah\")\n    end\n  end\n\n  if ActionController::Parameters.method_defined?(:expect)\n    describe \"#expected_attributes\" do\n      it \"checks policy for expected attributes\" do\n        params = to_params(\n          post: {\n            title: \"Hello\",\n            votes: 5,\n            admin: true\n          }\n        )\n\n        action = \"update\"\n\n        expect(Controller.new(user, action, params).expected_attributes(post).to_h).to eq(\n          \"title\" => \"Hello\",\n          \"votes\" => 5\n        )\n        expect(Controller.new(double, action, params).expected_attributes(post).to_h).to eq(\"votes\" => 5)\n      end\n\n      it \"checks policy for expected attributes for record of a ActiveModel type\" do\n        customer_post = Customer::Post.new(user)\n        params = to_params(\n          customer_post: {\n            title: \"Hello\",\n            votes: 5,\n            admin: true\n          }\n        )\n\n        action = \"update\"\n\n        expect(Controller.new(user, action, params).expected_attributes(customer_post).to_h).to eq(\n          \"title\" => \"Hello\",\n          \"votes\" => 5\n        )\n        expect(Controller.new(double, action, params).expected_attributes(customer_post).to_h).to eq(\n          \"votes\" => 5\n        )\n      end\n\n      it \"goes through the policy cache\" do\n        params = to_params(post: {title: \"Hello\"})\n        user = double\n        post = Post.new(user)\n        controller = Controller.new(user, \"update\", params)\n\n        expect do\n          expect(controller.expected_attributes(post)).to be_truthy\n          expect(controller.expected_attributes(post)).to be_truthy\n        end.to change { PostPolicy.instances }.by(1)\n      end\n    end\n\n    context \"action-specific expected attributes\" do\n      it \"is checked if it is defined in the policy\" do\n        params = to_params(\n          post: {\n            title: \"Hello\",\n            body: \"blah\",\n            votes: 5,\n            admin: true\n          }\n        )\n\n        action = \"revise\"\n        expect(Controller.new(user, action, params).expected_attributes(post).to_h).to eq(\"body\" => \"blah\")\n      end\n\n      it \"can be explicitly set\" do\n        params = to_params(\n          post: {\n            title: \"Hello\",\n            body: \"blah\",\n            votes: 5,\n            admin: true\n          }\n        )\n\n        action = \"update\"\n        controller = Controller.new(user, action, params)\n        expect(controller.expected_attributes(post, action: :revise).to_h).to eq(\"body\" => \"blah\")\n      end\n    end\n\n    it \"can be retrieved with an explicit param key\" do\n      params = to_params(admin_post: {title: \"Hello\"})\n\n      action = \"update\"\n      controller = Controller.new(user, action, params)\n      expect(controller.expected_attributes(post, param_key: \"admin_post\").to_h).to eq(\"title\" => \"Hello\")\n    end\n  end\n\n  describe \"#pundit_reset!\" do\n    it \"allows authorize to react to a user change\" do\n      expect(controller.authorize(post)).to be_truthy\n\n      controller.current_user = double\n      controller.pundit_reset!\n      expect { controller.authorize(post) }.to raise_error(Pundit::NotAuthorizedError)\n    end\n\n    it \"allows policy to react to a user change\" do\n      expect(controller.policy(DummyCurrentUser).user).to be user\n\n      new_user = double(\"new user\")\n      controller.current_user = new_user\n      controller.pundit_reset!\n      expect(controller.policy(DummyCurrentUser).user).to be new_user\n    end\n\n    it \"allows policy scope to react to a user change\" do\n      expect(controller.policy_scope(DummyCurrentUser)).to be user\n\n      new_user = double(\"new user\")\n      controller.current_user = new_user\n      controller.pundit_reset!\n      expect(controller.policy_scope(DummyCurrentUser)).to be new_user\n    end\n\n    it \"resets the pundit context\" do\n      expect(controller.pundit.user).to be(user)\n\n      new_user = double\n      controller.current_user = new_user\n      expect { controller.pundit_reset! }.to change { controller.pundit.user }.from(user).to(new_user)\n    end\n\n    it \"clears pundit_policy_authorized? flag\" do\n      expect(controller.pundit_policy_authorized?).to be false\n\n      controller.skip_authorization\n      expect(controller.pundit_policy_authorized?).to be true\n\n      controller.pundit_reset!\n      expect(controller.pundit_policy_authorized?).to be false\n    end\n\n    it \"clears pundit_policy_scoped? flag\" do\n      expect(controller.pundit_policy_scoped?).to be false\n\n      controller.skip_policy_scope\n      expect(controller.pundit_policy_scoped?).to be true\n\n      controller.pundit_reset!\n      expect(controller.pundit_policy_scoped?).to be false\n    end\n  end\nend\n"
  },
  {
    "path": "spec/generators_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire \"spec_helper\"\nrequire \"tmpdir\"\n\nrequire \"rails/generators\"\nrequire \"generators/pundit/install/install_generator\"\nrequire \"generators/pundit/policy/policy_generator\"\n\nRSpec.describe \"generators\" do\n  before(:all) do\n    @tmpdir = Dir.mktmpdir\n\n    Dir.chdir(@tmpdir) do\n      Pundit::Generators::InstallGenerator.new([], {quiet: true}).invoke_all\n      Pundit::Generators::PolicyGenerator.new(%w[Widget], {quiet: true}).invoke_all\n\n      require \"./app/policies/application_policy\"\n      require \"./app/policies/widget_policy\"\n    end\n  end\n\n  after(:all) do\n    FileUtils.remove_entry(@tmpdir)\n  end\n\n  describe \"WidgetPolicy\", type: :policy do\n    permissions :index?, :show?, :create?, :new?, :update?, :edit?, :destroy? do\n      it \"has safe defaults\" do\n        expect(WidgetPolicy).not_to permit(double(\"User\"), double(\"Widget\"))\n      end\n    end\n\n    describe \"WidgetPolicy::Scope\" do\n      describe \"#resolve\" do\n        it \"raises a descriptive error\" do\n          scope = WidgetPolicy::Scope.new(double(\"User\"), double(\"User.all\"))\n          expect { scope.resolve }.to raise_error(NoMethodError, /WidgetPolicy::Scope/)\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/policies/post_policy_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire \"spec_helper\"\n\nRSpec.describe PostPolicy do\n  let(:user) { double }\n  let(:own_post) { double(user: user) }\n  let(:other_post) { double(user: double) }\n  subject { described_class }\n\n  permissions :update?, :show? do\n    it \"is successful when all permissions match\" do\n      is_expected.to permit(user, own_post)\n    end\n\n    it \"fails when any permissions do not match\" do\n      expect do\n        is_expected.to permit(user, other_post)\n      end.to raise_error(RSpec::Expectations::ExpectationNotMetError)\n    end\n\n    it \"uses the default description if not overridden\" do\n      expect(permit(user, own_post).description).to eq(\"permit #{user.inspect} and #{own_post.inspect}\")\n    end\n\n    context \"when the matcher description is overridden\" do\n      after do\n        Pundit::RSpec::Matchers.description = nil\n      end\n\n      it \"sets a custom matcher description with a Proc\" do\n        allow(user).to receive(:role).and_return(\"default_role\")\n        allow(own_post).to receive(:id).and_return(1)\n\n        Pundit::RSpec::Matchers.description = lambda { |user, record|\n          \"permit user with role #{user.role} to access record with ID #{record.id}\"\n        }\n\n        description = permit(user, own_post).description\n        expect(description).to eq(\"permit user with role default_role to access record with ID 1\")\n      end\n\n      it \"sets a custom matcher description with a string\" do\n        Pundit::RSpec::Matchers.description = \"permit user\"\n        expect(permit(user, own_post).description).to eq(\"permit user\")\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/policy_finder_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire \"spec_helper\"\n\nRSpec.describe Pundit::PolicyFinder do\n  let(:user) { double }\n  let(:post) { Post.new(user) }\n  let(:comment) { CommentFourFiveSix.new }\n  let(:article) { Article.new }\n\n  describe \"SUFFIX\" do\n    specify { expect(described_class::SUFFIX).to eq \"Policy\" }\n    specify { expect(Pundit::SUFFIX).to eq(described_class::SUFFIX) }\n  end\n\n  describe \"#scope\" do\n    subject { described_class.new(post) }\n\n    it \"returns a policy scope\" do\n      expect(subject.scope).to eq PostPolicy::Scope\n    end\n\n    context \"policy is nil\" do\n      it \"returns nil\" do\n        allow(subject).to receive(:policy).and_return nil\n        expect(subject.scope).to eq nil\n      end\n    end\n  end\n\n  describe \"#policy\" do\n    context \"with an instance\" do\n      it \"returns the associated policy\" do\n        object = described_class.new(post)\n\n        expect(object.policy).to eq PostPolicy\n      end\n    end\n\n    context \"with an array of symbols\" do\n      it \"returns the associated namespaced policy\" do\n        object = described_class.new(%i[project post])\n\n        expect(object.policy).to eq Project::PostPolicy\n      end\n    end\n\n    context \"with an array of a symbol and an instance\" do\n      it \"returns the associated namespaced policy\" do\n        object = described_class.new([:project, post])\n\n        expect(object.policy).to eq Project::PostPolicy\n      end\n    end\n\n    context \"with an array of a symbol and a class with a specified policy class\" do\n      it \"returns the associated namespaced policy\" do\n        object = described_class.new([:project, Customer::Post])\n\n        expect(object.policy).to eq Project::PostPolicy\n      end\n    end\n\n    context \"with an array of a symbol and a class with a specified model name\" do\n      it \"returns the associated namespaced policy\" do\n        object = described_class.new([:project, CommentsRelation])\n\n        expect(object.policy).to eq Project::CommentPolicy\n      end\n    end\n\n    context \"with a class\" do\n      it \"returns the associated policy\" do\n        object = described_class.new(Post)\n\n        expect(object.policy).to eq PostPolicy\n      end\n    end\n\n    context \"with a class which has a specified policy class\" do\n      it \"returns the associated policy\" do\n        object = described_class.new(Customer::Post)\n\n        expect(object.policy).to eq PostPolicy\n      end\n    end\n\n    context \"with an instance which has a specified policy class\" do\n      it \"returns the associated policy\" do\n        object = described_class.new(Customer::Post.new(user))\n\n        expect(object.policy).to eq PostPolicy\n      end\n    end\n\n    context \"with a class which has a specified model name\" do\n      it \"returns the associated policy\" do\n        object = described_class.new(CommentsRelation)\n\n        expect(object.policy).to eq CommentPolicy\n      end\n    end\n\n    context \"with an instance which has a specified policy class\" do\n      it \"returns the associated policy\" do\n        object = described_class.new(CommentsRelation.new)\n\n        expect(object.policy).to eq CommentPolicy\n      end\n    end\n\n    context \"with nil\" do\n      it \"returns a NilClassPolicy\" do\n        object = described_class.new(nil)\n\n        expect(object.policy).to eq NilClassPolicy\n      end\n    end\n\n    context \"with a class that doesn't have an associated policy\" do\n      it \"returns nil\" do\n        object = described_class.new(Foo)\n\n        expect(object.policy).to eq nil\n      end\n    end\n  end\n\n  describe \"#scope!\" do\n    context \"@object is nil\" do\n      subject { described_class.new(nil) }\n\n      it \"returns the NilClass policy's scope class\" do\n        expect(subject.scope!).to eq NilClassPolicy::Scope\n      end\n    end\n\n    context \"@object is defined\" do\n      subject { described_class.new(post) }\n\n      it \"returns the scope\" do\n        expect(subject.scope!).to eq PostPolicy::Scope\n      end\n    end\n  end\n\n  describe \"#param_key\" do\n    context \"object responds to model_name\" do\n      subject { described_class.new(comment) }\n\n      it \"returns the param_key\" do\n        expect(subject.object).to respond_to(:model_name)\n        expect(subject.param_key).to eq \"comment_four_five_six\"\n      end\n    end\n\n    context \"object is a class\" do\n      subject { described_class.new(Article) }\n\n      it \"returns the param_key\" do\n        expect(subject.object).not_to respond_to(:model_name)\n        expect(subject.object).to be_a Class\n        expect(subject.param_key).to eq \"article\"\n      end\n    end\n\n    context \"object is an instance of a class\" do\n      subject { described_class.new(article) }\n\n      it \"returns the param_key\" do\n        expect(subject.object).not_to respond_to(:model_name)\n        expect(subject.object).not_to be_a Class\n        expect(subject.object).to be_an_instance_of Article\n\n        expect(subject.param_key).to eq \"article\"\n      end\n    end\n\n    context \"object is an array\" do\n      subject { described_class.new([:project, article]) }\n\n      it \"returns the param_key for the last element of the array\" do\n        expect(subject.object).not_to respond_to(:model_name)\n        expect(subject.object).not_to be_a Class\n        expect(subject.object).to be_an_instance_of Array\n\n        expect(subject.param_key).to eq \"article\"\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/pundit/helper_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire \"spec_helper\"\n\nRSpec.describe Pundit::Helper do\n  let(:user) { double }\n  let(:controller) { Controller.new(user, \"update\", double) }\n  let(:view) { Controller::View.new(controller) }\n\n  describe \"#policy_scope\" do\n    it \"doesn't flip pundit_policy_scoped?\" do\n      scoped = view.policy_scope(Post)\n\n      expect(scoped).to be(Post.published)\n      expect(controller).not_to be_pundit_policy_scoped\n    end\n  end\nend\n"
  },
  {
    "path": "spec/pundit_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire \"spec_helper\"\n\nRSpec.describe Pundit do\n  let(:user) { double }\n  let(:post) { Post.new(user) }\n  let(:customer_post) { Customer::Post.new(user) }\n  let(:post_four_five_six) { PostFourFiveSix.new(user) }\n  let(:comment) { Comment.new }\n  let(:comment_four_five_six) { CommentFourFiveSix.new }\n  let(:article) { Article.new }\n  let(:artificial_blog) { ArtificialBlog.new }\n  let(:article_tag) { ArticleTag.new }\n  let(:comments_relation) { CommentsRelation.new(empty: false) }\n  let(:empty_comments_relation) { CommentsRelation.new(empty: true) }\n  let(:tag_four_five_six) { ProjectOneTwoThree::TagFourFiveSix.new(user) }\n  let(:avatar_four_five_six) { ProjectOneTwoThree::AvatarFourFiveSix.new }\n  let(:wiki) { Wiki.new }\n\n  describe \".authorize\" do\n    it \"infers the policy and authorizes based on it\" do\n      expect(Pundit.authorize(user, post, :update?)).to be_truthy\n    end\n\n    it \"returns the record on successful authorization\" do\n      expect(Pundit.authorize(user, post, :update?)).to eq(post)\n    end\n\n    it \"returns the record when passed record with namespace \" do\n      expect(Pundit.authorize(user, [:project, comment], :update?)).to eq(comment)\n    end\n\n    it \"returns the record when passed record with nested namespace \" do\n      expect(Pundit.authorize(user, [:project, :admin, comment], :update?)).to eq(comment)\n    end\n\n    it \"returns the policy name symbol when passed record with headless policy\" do\n      expect(Pundit.authorize(user, :publication, :create?)).to eq(:publication)\n    end\n\n    it \"returns the class when passed record not a particular instance\" do\n      expect(Pundit.authorize(user, Post, :show?)).to eq(Post)\n    end\n\n    it \"works with anonymous class policies\" do\n      expect(Pundit.authorize(user, article_tag, :show?)).to be_truthy\n      expect { Pundit.authorize(user, article_tag, :destroy?) }.to raise_error(Pundit::NotAuthorizedError)\n    end\n\n    it \"raises an error with the policy, query and record\" do\n      # rubocop:disable Style/MultilineBlockChain\n      expect do\n        Pundit.authorize(user, post, :destroy?)\n      end.to raise_error(Pundit::NotAuthorizedError, \"not allowed to PostPolicy#destroy? this Post\") do |error|\n        expect(error.query).to eq :destroy?\n        expect(error.record).to eq post\n        expect(error.policy).to have_attributes(\n          user: user,\n          record: post\n        )\n        expect(error.policy).to be_a(PostPolicy)\n      end\n      # rubocop:enable Style/MultilineBlockChain\n    end\n\n    it \"raises an error with the policy, query and record when the record is namespaced\" do\n      # rubocop:disable Style/MultilineBlockChain\n      expect do\n        Pundit.authorize(user, [:project, :admin, comment], :destroy?)\n      end.to raise_error(Pundit::NotAuthorizedError,\n        \"not allowed to Project::Admin::CommentPolicy#destroy? this Comment\") do |error|\n        expect(error.query).to eq :destroy?\n        expect(error.record).to eq comment\n        expect(error.policy).to have_attributes(\n          user: user,\n          record: comment\n        )\n        expect(error.policy).to be_a(Project::Admin::CommentPolicy)\n      end\n      # rubocop:enable Style/MultilineBlockChain\n    end\n\n    it \"raises an error with the policy, query and the class name when a Class is given\" do\n      # rubocop:disable Style/MultilineBlockChain\n      expect do\n        Pundit.authorize(user, Post, :destroy?)\n      end.to raise_error(Pundit::NotAuthorizedError, \"not allowed to PostPolicy#destroy? Post\") do |error|\n        expect(error.query).to eq :destroy?\n        expect(error.record).to eq Post\n        expect(error.policy).to have_attributes(\n          user: user,\n          record: Post\n        )\n        expect(error.policy).to be_a(PostPolicy)\n      end\n      # rubocop:enable Style/MultilineBlockChain\n    end\n\n    it \"raises an error with a invalid policy constructor\" do\n      expect do\n        Pundit.authorize(user, wiki, :update?)\n      end.to raise_error(Pundit::InvalidConstructorError, \"Invalid #<WikiPolicy> constructor is called\")\n    end\n\n    context \"when passed a policy class\" do\n      it \"uses the passed policy class\" do\n        expect(Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy)).to be_truthy\n      end\n\n      # This is documenting past behaviour.\n      it \"doesn't cache the policy class\" do\n        cache = {}\n\n        expect do\n          Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy, cache: cache)\n          Pundit.authorize(user, post, :create?, policy_class: PublicationPolicy, cache: cache)\n        end.to change { PublicationPolicy.instances }.by(2)\n      end\n    end\n\n    context \"when passed a policy class while simultaenously passing a namespace\" do\n      it \"uses the passed policy class\" do\n        expect(PublicationPolicy).to receive(:new).with(user, comment).and_call_original\n        expect(Pundit.authorize(user, [:project, comment], :create?, policy_class: PublicationPolicy)).to be_truthy\n      end\n    end\n\n    context \"when passed an explicit cache\" do\n      it \"uses the hash assignment interface on the cache\" do\n        custom_cache = CustomCache.new\n\n        Pundit.authorize(user, post, :update?, cache: custom_cache)\n\n        expect(custom_cache.to_h).to match({\n          post => kind_of(PostPolicy)\n        })\n      end\n    end\n  end\n\n  describe \".policy_scope\" do\n    it \"returns an instantiated policy scope given a plain model class\" do\n      expect(Pundit.policy_scope(user, Post)).to eq :published\n    end\n\n    it \"returns an instantiated policy scope given an active model class\" do\n      expect(Pundit.policy_scope(user, Comment)).to eq CommentScope.new(Comment)\n    end\n\n    it \"returns an instantiated policy scope given an active record relation\" do\n      expect(Pundit.policy_scope(user, comments_relation)).to eq CommentScope.new(comments_relation)\n    end\n\n    it \"returns an instantiated policy scope given an empty active record relation\" do\n      expect(Pundit.policy_scope(user, empty_comments_relation)).to eq CommentScope.new(empty_comments_relation)\n    end\n\n    it \"returns an instantiated policy scope given an array of a symbol and plain model class\" do\n      expect(Pundit.policy_scope(user, [:project, Post])).to eq :read\n    end\n\n    it \"returns an instantiated policy scope given an array of a symbol and active model class\" do\n      expect(Pundit.policy_scope(user, [:project, Comment])).to eq Comment\n    end\n\n    it \"returns nil if the given policy scope can't be found\" do\n      expect(Pundit.policy_scope(user, Article)).to be_nil\n    end\n\n    it \"raises an exception if nil object given\" do\n      expect { Pundit.policy_scope(user, nil) }.to raise_error(Pundit::NotDefinedError)\n    end\n\n    it \"raises an error with a invalid policy scope constructor\" do\n      expect do\n        Pundit.policy_scope(user, Wiki)\n      end.to raise_error(Pundit::InvalidConstructorError, \"Invalid #<WikiPolicy::Scope> constructor is called\")\n    end\n\n    it \"raises an original error with a policy scope that contains error\" do\n      expect do\n        Pundit.policy_scope(user, DefaultScopeContainsError)\n      end.to raise_error(RuntimeError, \"This is an arbitrary error that should bubble up\")\n    end\n  end\n\n  describe \".policy_scope!\" do\n    it \"returns an instantiated policy scope given a plain model class\" do\n      expect(Pundit.policy_scope!(user, Post)).to eq :published\n    end\n\n    it \"returns an instantiated policy scope given an active model class\" do\n      expect(Pundit.policy_scope!(user, Comment)).to eq CommentScope.new(Comment)\n    end\n\n    it \"throws an exception if the given policy scope can't be found\" do\n      expect { Pundit.policy_scope!(user, Article) }.to raise_error(Pundit::NotDefinedError)\n    end\n\n    it \"throws an exception if the given policy scope can't be found\" do\n      expect { Pundit.policy_scope!(user, ArticleTag) }.to raise_error(Pundit::NotDefinedError)\n    end\n\n    it \"throws an exception if the given policy scope is nil\" do\n      expect do\n        Pundit.policy_scope!(user, nil)\n      end.to raise_error(Pundit::NotDefinedError, \"Cannot scope NilClass\")\n    end\n\n    it \"returns an instantiated policy scope given an array of a symbol and plain model class\" do\n      expect(Pundit.policy_scope!(user, [:project, Post])).to eq :read\n    end\n\n    it \"returns an instantiated policy scope given an array of a symbol and active model class\" do\n      expect(Pundit.policy_scope!(user, [:project, Comment])).to eq Comment\n    end\n\n    it \"raises an error with a invalid policy scope constructor\" do\n      expect do\n        Pundit.policy_scope(user, Wiki)\n      end.to raise_error(Pundit::InvalidConstructorError, \"Invalid #<WikiPolicy::Scope> constructor is called\")\n    end\n  end\n\n  describe \".policy\" do\n    it \"returns an instantiated policy given a plain model instance\" do\n      policy = Pundit.policy(user, post)\n      expect(policy.user).to eq user\n      expect(policy.post).to eq post\n    end\n\n    it \"returns an instantiated policy given an active model instance\" do\n      policy = Pundit.policy(user, comment)\n      expect(policy.user).to eq user\n      expect(policy.comment).to eq comment\n    end\n\n    it \"returns an instantiated policy given a plain model class\" do\n      policy = Pundit.policy(user, Post)\n      expect(policy.user).to eq user\n      expect(policy.post).to eq Post\n    end\n\n    it \"returns an instantiated policy given an active model class\" do\n      policy = Pundit.policy(user, Comment)\n      expect(policy.user).to eq user\n      expect(policy.comment).to eq Comment\n    end\n\n    it \"returns an instantiated policy given a symbol\" do\n      policy = Pundit.policy(user, :criteria)\n      expect(policy.class).to eq CriteriaPolicy\n      expect(policy.user).to eq user\n      expect(policy.criteria).to eq :criteria\n    end\n\n    it \"returns an instantiated policy given an array of symbols\" do\n      policy = Pundit.policy(user, %i[project criteria])\n      expect(policy.class).to eq Project::CriteriaPolicy\n      expect(policy.user).to eq user\n      expect(policy.criteria).to eq :criteria\n    end\n\n    it \"returns an instantiated policy given an array of a symbol and plain model instance\" do\n      policy = Pundit.policy(user, [:project, post])\n      expect(policy.class).to eq Project::PostPolicy\n      expect(policy.user).to eq user\n      expect(policy.post).to eq post\n    end\n\n    it \"returns an instantiated policy given an array of a symbol and a model instance with policy_class override\" do\n      policy = Pundit.policy(user, [:project, customer_post])\n      expect(policy.class).to eq Project::PostPolicy\n      expect(policy.user).to eq user\n      expect(policy.post).to eq customer_post\n    end\n\n    it \"returns an instantiated policy given an array of a symbol and an active model instance\" do\n      policy = Pundit.policy(user, [:project, comment])\n      expect(policy.class).to eq Project::CommentPolicy\n      expect(policy.user).to eq user\n      expect(policy.comment).to eq comment\n    end\n\n    it \"returns an instantiated policy given an array of a symbol and a plain model class\" do\n      policy = Pundit.policy(user, [:project, Post])\n      expect(policy.class).to eq Project::PostPolicy\n      expect(policy.user).to eq user\n      expect(policy.post).to eq Post\n    end\n\n    it \"raises an error with a invalid policy constructor\" do\n      expect do\n        Pundit.policy(user, Wiki)\n      end.to raise_error(Pundit::InvalidConstructorError, \"Invalid #<WikiPolicy> constructor is called\")\n    end\n\n    it \"returns an instantiated policy given an array of a symbol and an active model class\" do\n      policy = Pundit.policy(user, [:project, Comment])\n      expect(policy.class).to eq Project::CommentPolicy\n      expect(policy.user).to eq user\n      expect(policy.comment).to eq Comment\n    end\n\n    it \"returns an instantiated policy given an array of a symbol and a class with policy_class override\" do\n      policy = Pundit.policy(user, [:project, Customer::Post])\n      expect(policy.class).to eq Project::PostPolicy\n      expect(policy.user).to eq user\n      expect(policy.post).to eq Customer::Post\n    end\n\n    it \"returns correct policy class for an array of a multi-word symbols\" do\n      policy = Pundit.policy(user, %i[project_one_two_three criteria_four_five_six])\n      expect(policy.class).to eq ProjectOneTwoThree::CriteriaFourFiveSixPolicy\n    end\n\n    it \"returns correct policy class for an array of a multi-word symbol and a multi-word plain model instance\" do\n      policy = Pundit.policy(user, [:project_one_two_three, post_four_five_six])\n      expect(policy.class).to eq ProjectOneTwoThree::PostFourFiveSixPolicy\n    end\n\n    it \"returns correct policy class for an array of a multi-word symbol and a multi-word active model instance\" do\n      policy = Pundit.policy(user, [:project_one_two_three, comment_four_five_six])\n      expect(policy.class).to eq ProjectOneTwoThree::CommentFourFiveSixPolicy\n    end\n\n    it \"returns correct policy class for an array of a multi-word symbol and a multi-word plain model class\" do\n      policy = Pundit.policy(user, [:project_one_two_three, PostFourFiveSix])\n      expect(policy.class).to eq ProjectOneTwoThree::PostFourFiveSixPolicy\n    end\n\n    it \"returns correct policy class for an array of a multi-word symbol and a multi-word active model class\" do\n      policy = Pundit.policy(user, [:project_one_two_three, CommentFourFiveSix])\n      expect(policy.class).to eq ProjectOneTwoThree::CommentFourFiveSixPolicy\n    end\n\n    it \"returns correct policy class for a multi-word scoped plain model class\" do\n      policy = Pundit.policy(user, ProjectOneTwoThree::TagFourFiveSix)\n      expect(policy.class).to eq ProjectOneTwoThree::TagFourFiveSixPolicy\n    end\n\n    it \"returns correct policy class for a multi-word scoped plain model instance\" do\n      policy = Pundit.policy(user, tag_four_five_six)\n      expect(policy.class).to eq ProjectOneTwoThree::TagFourFiveSixPolicy\n    end\n\n    it \"returns correct policy class for a multi-word scoped active model class\" do\n      policy = Pundit.policy(user, ProjectOneTwoThree::AvatarFourFiveSix)\n      expect(policy.class).to eq ProjectOneTwoThree::AvatarFourFiveSixPolicy\n    end\n\n    it \"returns correct policy class for a multi-word scoped active model instance\" do\n      policy = Pundit.policy(user, avatar_four_five_six)\n      expect(policy.class).to eq ProjectOneTwoThree::AvatarFourFiveSixPolicy\n    end\n\n    it \"returns nil if the given policy can't be found\" do\n      expect(Pundit.policy(user, article)).to be_nil\n      expect(Pundit.policy(user, Article)).to be_nil\n    end\n\n    it \"returns the specified NilClassPolicy for nil\" do\n      expect(Pundit.policy(user, nil)).to be_a NilClassPolicy\n    end\n\n    describe \"with .policy_class set on the model\" do\n      it \"returns an instantiated policy given a plain model instance\" do\n        policy = Pundit.policy(user, artificial_blog)\n        expect(policy.user).to eq user\n        expect(policy.blog).to eq artificial_blog\n      end\n\n      it \"returns an instantiated policy given a plain model class\" do\n        policy = Pundit.policy(user, ArtificialBlog)\n        expect(policy.user).to eq user\n        expect(policy.blog).to eq ArtificialBlog\n      end\n\n      it \"returns an instantiated policy given a plain model instance providing an anonymous class\" do\n        policy = Pundit.policy(user, article_tag)\n        expect(policy.user).to eq user\n        expect(policy.tag).to eq article_tag\n      end\n\n      it \"returns an instantiated policy given a plain model class providing an anonymous class\" do\n        policy = Pundit.policy(user, ArticleTag)\n        expect(policy.user).to eq user\n        expect(policy.tag).to eq ArticleTag\n      end\n    end\n  end\n\n  describe \".policy!\" do\n    it \"returns an instantiated policy given a plain model instance\" do\n      policy = Pundit.policy!(user, post)\n      expect(policy.user).to eq user\n      expect(policy.post).to eq post\n    end\n\n    it \"returns an instantiated policy given an active model instance\" do\n      policy = Pundit.policy!(user, comment)\n      expect(policy.user).to eq user\n      expect(policy.comment).to eq comment\n    end\n\n    it \"returns an instantiated policy given a plain model class\" do\n      policy = Pundit.policy!(user, Post)\n      expect(policy.user).to eq user\n      expect(policy.post).to eq Post\n    end\n\n    it \"returns an instantiated policy given an active model class\" do\n      policy = Pundit.policy!(user, Comment)\n      expect(policy.user).to eq user\n      expect(policy.comment).to eq Comment\n    end\n\n    it \"returns an instantiated policy given a symbol\" do\n      policy = Pundit.policy!(user, :criteria)\n      expect(policy.class).to eq CriteriaPolicy\n      expect(policy.user).to eq user\n      expect(policy.criteria).to eq :criteria\n    end\n\n    it \"returns an instantiated policy given an array of symbols\" do\n      policy = Pundit.policy!(user, %i[project criteria])\n      expect(policy.class).to eq Project::CriteriaPolicy\n      expect(policy.user).to eq user\n      expect(policy.criteria).to eq :criteria\n    end\n\n    it \"throws an exception if the given policy can't be found\" do\n      expect { Pundit.policy!(user, article) }.to raise_error(Pundit::NotDefinedError)\n      expect { Pundit.policy!(user, Article) }.to raise_error(Pundit::NotDefinedError)\n    end\n\n    it \"returns the specified NilClassPolicy for nil\" do\n      expect(Pundit.policy!(user, nil)).to be_a NilClassPolicy\n    end\n\n    it \"raises an error with a invalid policy constructor\" do\n      expect do\n        Pundit.policy(user, Wiki)\n      end.to raise_error(Pundit::InvalidConstructorError, \"Invalid #<WikiPolicy> constructor is called\")\n    end\n  end\n\n  describe \".included\" do\n    it \"includes Authorization module\" do\n      klass = Class.new\n\n      expect do\n        klass.include Pundit\n      end.to output.to_stderr\n\n      expect(klass).to include Pundit::Authorization\n    end\n\n    it \"warns about deprecation\" do\n      klass = Class.new\n      expect do\n        klass.include Pundit\n      end.to output(a_string_starting_with(\"'include Pundit' is deprecated\")).to_stderr\n    end\n  end\n\n  describe \"Pundit::NotAuthorizedError\" do\n    it \"can be initialized with a string as message\" do\n      error = Pundit::NotAuthorizedError.new(\"must be logged in\")\n      expect(error.message).to eq \"must be logged in\"\n    end\n  end\nend\n"
  },
  {
    "path": "spec/rspec_dsl_spec.rb",
    "content": "# frozen_string_literal: true\n\nrequire \"spec_helper\"\n\nRSpec.describe \"Pundit RSpec DSL\", type: :policy do\n  let(:fake_rspec) do\n    double = class_double(RSpec::Core::ExampleGroup)\n    double.extend(::Pundit::RSpec::DSL)\n    double\n  end\n  let(:block) { proc { \"block content\" } }\n\n  let(:user) { double }\n  let(:other_user) { double }\n  let(:post) { Post.new(user) }\n  let(:policy) { PostPolicy }\n\n  it \"calls describe with the correct metadata and without :focus\" do\n    expected_metadata = {permissions: %i[item1 item2], caller: instance_of(Array)}\n    expect(fake_rspec).to receive(:describe).with(\"item1 and item2\", match(expected_metadata)) do |&block|\n      expect(block.call).to eq(\"block content\")\n    end\n\n    fake_rspec.permissions(:item1, :item2, &block)\n  end\n\n  it \"calls describe with the correct metadata and with :focus\" do\n    expected_metadata = {permissions: %i[item1 item2], caller: instance_of(Array), focus: true}\n    expect(fake_rspec).to receive(:describe).with(\"item1 and item2\", match(expected_metadata)) do |&block|\n      expect(block.call).to eq(\"block content\")\n    end\n\n    fake_rspec.permissions(:item1, :item2, :focus, &block)\n  end\n\n  describe \"#permit\" do\n    context \"when not appropriately wrapped in permissions\" do\n      it \"raises a descriptive error\" do\n        expect do\n          expect(policy).to permit(user, post)\n        end.to raise_error(KeyError, <<~MSG.strip)\n          No permissions in example metadata, did you forget to wrap with `permissions :show?, ...`?\n        MSG\n      end\n    end\n\n    permissions :edit?, :update? do\n      it \"succeeds when action is permitted\" do\n        expect(policy).to permit(user, post)\n      end\n\n      context \"when it fails\" do\n        it \"fails with a descriptive error message\" do\n          expect do\n            expect(policy).to permit(other_user, post)\n          end.to raise_error(RSpec::Expectations::ExpectationNotMetError, <<~MSG.strip)\n            Expected PostPolicy to grant edit? and update? on Post but edit? and update? were not granted\n          MSG\n        end\n      end\n\n      context \"when negated\" do\n        it \"succeeds when action is not permitted\" do\n          expect(policy).not_to permit(other_user, post)\n        end\n\n        context \"when it fails\" do\n          it \"fails with a descriptive error message\" do\n            expect do\n              expect(policy).not_to permit(user, post)\n            end.to raise_error(RSpec::Expectations::ExpectationNotMetError, <<~MSG.strip)\n              Expected PostPolicy not to grant edit? and update? on Post but edit? and update? were granted\n            MSG\n          end\n        end\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/spec_helper.rb",
    "content": "# frozen_string_literal: true\n\nif ENV[\"COVERAGE\"]\n  require \"simplecov\"\n  require \"simplecov_json_formatter\"\n\n  SimpleCov.formatters = SimpleCov::Formatter::MultiFormatter.new([\n    SimpleCov::Formatter::HTMLFormatter,\n    SimpleCov::Formatter::JSONFormatter\n  ])\n\n  SimpleCov.start do\n    enable_coverage :branch\n    primary_coverage :branch\n  end\n\n  SimpleCov.minimum_coverage_by_file line: 100, branch: 100\nend\n\n# @see https://github.com/rails/rails/issues/54260\nrequire \"logger\" if RUBY_ENGINE == \"jruby\" && RUBY_ENGINE_VERSION.start_with?(\"9.3\")\n\nrequire \"pundit\"\nrequire \"pundit/rspec\"\nrequire \"active_model/naming\"\n\n# Load all supporting files: models, policies, etc.\nrequire \"zeitwerk\"\nloader = Zeitwerk::Loader.new\nloader.push_dir(File.expand_path(\"support/models\", __dir__))\nloader.push_dir(File.expand_path(\"support/policies\", __dir__))\nloader.push_dir(File.expand_path(\"support/lib\", __dir__))\nloader.setup\nloader.eager_load\n"
  },
  {
    "path": "spec/support/lib/controller.rb",
    "content": "# frozen_string_literal: true\n\nclass Controller\n  attr_accessor :current_user\n  attr_reader :action_name, :params\n\n  class View\n    def initialize(controller)\n      @controller = controller\n    end\n\n    attr_reader :controller\n  end\n\n  class << self\n    def helper(mod)\n      View.include(mod)\n    end\n\n    def helper_method(method)\n      View.class_eval <<-RUBY, __FILE__, __LINE__ + 1\n        def #{method}(*args, **kwargs, &block)\n          controller.send(:#{method}, *args, **kwargs, &block)\n        end\n      RUBY\n    end\n  end\n\n  include Pundit::Authorization\n\n  # Mark protected methods public so they may be called in test\n  public(*Pundit::Authorization.protected_instance_methods)\n\n  def initialize(current_user, action_name, params)\n    @current_user = current_user\n    @action_name = action_name\n    @params = params\n  end\nend\n"
  },
  {
    "path": "spec/support/lib/custom_cache.rb",
    "content": "# frozen_string_literal: true\n\nclass CustomCache\n  def initialize\n    @store = {}\n  end\n\n  def to_h\n    @store\n  end\n\n  def [](key)\n    @store[key]\n  end\n\n  def []=(key, value)\n    @store[key] = value\n  end\nend\n"
  },
  {
    "path": "spec/support/lib/instance_tracking.rb",
    "content": "# frozen_string_literal: true\n\nmodule InstanceTracking\n  module ClassMethods\n    def instances\n      @instances || 0\n    end\n\n    attr_writer :instances\n  end\n\n  def self.prepended(other)\n    other.extend(ClassMethods)\n  end\n\n  def initialize(*args, **kwargs, &block)\n    self.class.instances += 1\n    super\n  end\nend\n"
  },
  {
    "path": "spec/support/models/article.rb",
    "content": "# frozen_string_literal: true\n\nclass Article\nend\n"
  },
  {
    "path": "spec/support/models/article_tag.rb",
    "content": "# frozen_string_literal: true\n\nclass ArticleTag\n  def self.policy_class\n    ArticleTagOtherNamePolicy\n  end\nend\n"
  },
  {
    "path": "spec/support/models/artificial_blog.rb",
    "content": "# frozen_string_literal: true\n\nclass ArtificialBlog < Blog\n  def self.policy_class\n    BlogPolicy\n  end\nend\n"
  },
  {
    "path": "spec/support/models/blog.rb",
    "content": "# frozen_string_literal: true\n\nclass Blog\nend\n"
  },
  {
    "path": "spec/support/models/comment.rb",
    "content": "# frozen_string_literal: true\n\nclass Comment\n  extend ActiveModel::Naming\nend\n"
  },
  {
    "path": "spec/support/models/comment_four_five_six.rb",
    "content": "# frozen_string_literal: true\n\nclass CommentFourFiveSix\n  extend ActiveModel::Naming\nend\n"
  },
  {
    "path": "spec/support/models/comment_scope.rb",
    "content": "# frozen_string_literal: true\n\nclass CommentScope\n  attr_reader :original_object\n\n  def initialize(original_object)\n    @original_object = original_object\n  end\n\n  def ==(other)\n    original_object == other.original_object\n  end\nend\n"
  },
  {
    "path": "spec/support/models/comments_relation.rb",
    "content": "# frozen_string_literal: true\n\nclass CommentsRelation\n  def initialize(empty: false)\n    @empty = empty\n  end\n\n  def self.model_name\n    Comment.model_name\n  end\nend\n"
  },
  {
    "path": "spec/support/models/customer/post.rb",
    "content": "# frozen_string_literal: true\n\nmodule Customer\n  class Post < ::Post\n    extend ActiveModel::Naming\n\n    def self.policy_class\n      PostPolicy\n    end\n  end\nend\n"
  },
  {
    "path": "spec/support/models/default_scope_contains_error.rb",
    "content": "# frozen_string_literal: true\n\nclass DefaultScopeContainsError\n  def self.all\n  end\nend\n"
  },
  {
    "path": "spec/support/models/dummy_current_user.rb",
    "content": "# frozen_string_literal: true\n\nclass DummyCurrentUser\nend\n"
  },
  {
    "path": "spec/support/models/foo.rb",
    "content": "# frozen_string_literal: true\n\nclass Foo\nend\n"
  },
  {
    "path": "spec/support/models/post.rb",
    "content": "# frozen_string_literal: true\n\nclass Post\n  def initialize(user = nil)\n    @user = user\n  end\n\n  attr_reader :user\n\n  def self.published\n    :published\n  end\n\n  def self.read\n    :read\n  end\n\n  def to_s\n    \"Post\"\n  end\nend\n"
  },
  {
    "path": "spec/support/models/post_four_five_six.rb",
    "content": "# frozen_string_literal: true\n\nclass PostFourFiveSix\n  def initialize(user)\n    @user = user\n  end\n\n  attr_reader(:user)\nend\n"
  },
  {
    "path": "spec/support/models/project_one_two_three/avatar_four_five_six.rb",
    "content": "# frozen_string_literal: true\n\nmodule ProjectOneTwoThree\n  class AvatarFourFiveSix\n    extend ActiveModel::Naming\n  end\nend\n"
  },
  {
    "path": "spec/support/models/project_one_two_three/tag_four_five_six.rb",
    "content": "# frozen_string_literal: true\n\nmodule ProjectOneTwoThree\n  class TagFourFiveSix\n    def initialize(user)\n      @user = user\n    end\n\n    attr_reader(:user)\n  end\nend\n"
  },
  {
    "path": "spec/support/models/wiki.rb",
    "content": "# frozen_string_literal: true\n\nclass Wiki\nend\n"
  },
  {
    "path": "spec/support/policies/article_tag_other_name_policy.rb",
    "content": "# frozen_string_literal: true\n\nclass ArticleTagOtherNamePolicy < BasePolicy\n  def show?\n    true\n  end\n\n  def destroy?\n    false\n  end\n\n  alias_method :tag, :record\nend\n"
  },
  {
    "path": "spec/support/policies/base_policy.rb",
    "content": "# frozen_string_literal: true\n\nclass BasePolicy\n  prepend InstanceTracking\n\n  class BaseScope\n    prepend InstanceTracking\n\n    def initialize(user, scope)\n      @user = user\n      @scope = scope\n    end\n\n    attr_reader :user, :scope\n  end\n\n  def initialize(user, record)\n    @user = user\n    @record = record\n  end\n\n  attr_reader :user, :record\nend\n"
  },
  {
    "path": "spec/support/policies/blog_policy.rb",
    "content": "# frozen_string_literal: true\n\nclass BlogPolicy < BasePolicy\n  alias_method :blog, :record\nend\n"
  },
  {
    "path": "spec/support/policies/comment_policy.rb",
    "content": "# frozen_string_literal: true\n\nclass CommentPolicy < BasePolicy\n  class Scope < BaseScope\n    def resolve\n      CommentScope.new(scope)\n    end\n  end\n\n  alias_method :comment, :record\nend\n"
  },
  {
    "path": "spec/support/policies/criteria_policy.rb",
    "content": "# frozen_string_literal: true\n\nclass CriteriaPolicy < BasePolicy\n  alias_method :criteria, :record\nend\n"
  },
  {
    "path": "spec/support/policies/default_scope_contains_error_policy.rb",
    "content": "# frozen_string_literal: true\n\nclass DefaultScopeContainsErrorPolicy < BasePolicy\n  class Scope < BaseScope\n    def resolve\n      # deliberate wrong usage of the method\n      raise \"This is an arbitrary error that should bubble up\"\n    end\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/dummy_current_user_policy.rb",
    "content": "# frozen_string_literal: true\n\nclass DummyCurrentUserPolicy < BasePolicy\n  class Scope < BasePolicy::BaseScope\n    def resolve\n      user\n    end\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/nil_class_policy.rb",
    "content": "# frozen_string_literal: true\n\nclass NilClassPolicy < BasePolicy\n  class Scope\n    def initialize(*)\n      raise Pundit::NotDefinedError, \"Cannot scope NilClass\"\n    end\n  end\n\n  def destroy?\n    false\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/post_policy.rb",
    "content": "# frozen_string_literal: true\n\nclass PostPolicy < BasePolicy\n  class Scope < BaseScope\n    def resolve\n      scope.published\n    end\n  end\n\n  alias_method :post, :record\n\n  def update?\n    post.user == user\n  end\n  alias_method :edit?, :update?\n\n  def destroy?\n    false\n  end\n\n  def show?\n    true\n  end\n\n  def permitted_attributes\n    if post.user == user\n      %i[title votes]\n    else\n      [:votes]\n    end\n  end\n\n  def permitted_attributes_for_revise\n    [:body]\n  end\n\n  def expected_attributes_for_action(action_name)\n    case action_name.to_sym\n    when :revise\n      [:body]\n    else\n      if post.user == user\n        %i[title votes]\n      else\n        [:votes]\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/project/admin/comment_policy.rb",
    "content": "# frozen_string_literal: true\n\nmodule Project\n  module Admin\n    class CommentPolicy < BasePolicy\n      def update?\n        true\n      end\n\n      def destroy?\n        false\n      end\n    end\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/project/comment_policy.rb",
    "content": "# frozen_string_literal: true\n\nmodule Project\n  class CommentPolicy < BasePolicy\n    class Scope < BaseScope\n      def resolve\n        scope\n      end\n    end\n\n    def update?\n      true\n    end\n\n    alias_method :comment, :record\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/project/criteria_policy.rb",
    "content": "# frozen_string_literal: true\n\nmodule Project\n  class CriteriaPolicy < BasePolicy\n    alias_method :criteria, :record\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/project/post_policy.rb",
    "content": "# frozen_string_literal: true\n\nmodule Project\n  class PostPolicy < BasePolicy\n    class Scope < BaseScope\n      def resolve\n        scope.read\n      end\n    end\n\n    alias_method :post, :record\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/project_one_two_three/avatar_four_five_six_policy.rb",
    "content": "# frozen_string_literal: true\n\nmodule ProjectOneTwoThree\n  class AvatarFourFiveSixPolicy < BasePolicy\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/project_one_two_three/comment_four_five_six_policy.rb",
    "content": "# frozen_string_literal: true\n\nmodule ProjectOneTwoThree\n  class CommentFourFiveSixPolicy < BasePolicy\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/project_one_two_three/criteria_four_five_six_policy.rb",
    "content": "# frozen_string_literal: true\n\nmodule ProjectOneTwoThree\n  class CriteriaFourFiveSixPolicy < BasePolicy\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/project_one_two_three/post_four_five_six_policy.rb",
    "content": "# frozen_string_literal: true\n\nmodule ProjectOneTwoThree\n  class PostFourFiveSixPolicy < BasePolicy\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/project_one_two_three/tag_four_five_six_policy.rb",
    "content": "# frozen_string_literal: true\n\nmodule ProjectOneTwoThree\n  class TagFourFiveSixPolicy < BasePolicy\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/publication_policy.rb",
    "content": "# frozen_string_literal: true\n\nclass PublicationPolicy < BasePolicy\n  class Scope < BaseScope\n    def resolve\n      scope.published\n    end\n  end\n\n  def create?\n    true\n  end\nend\n"
  },
  {
    "path": "spec/support/policies/wiki_policy.rb",
    "content": "# frozen_string_literal: true\n\nclass WikiPolicy\n  class Scope\n    # deliberate typo method\n    def initalize\n    end\n  end\nend\n"
  }
]