1"use strict";(self.webpackChunkgatsby_starter_default=self.webpackChunkgatsby_starter_default||[]).push([[3902],{89880:function(n,e,a){a.r(e),a.d(e,{Head:function(){return f},default:function(){return b}});var s=a(28453),t=a(96540);function o(n){const e=Object.assign({p:"p",a:"a",h2:"h2",span:"span",ul:"ul",li:"li",strong:"strong",h3:"h3"},(0,s.R)(),n.components);return t.createElement(t.Fragment,null,t.createElement(e.p,null,"One of the most critical aspects of building a web application\nis ensuring that users can only access the parts of the application\nthey are authorized to use.\nRails,\na robust web framework,\nprovides several tools\nand\ngems to help developers implement authorization efficiently.\nOne such gem is\n",t.createElement(e.a,{href:"https://github.com/varvet/pundit"},"Pundit"),",\na simple,\nlightweight authorization library that integrates seamlessly with Rails."),"\n",t.createElement(e.h2,{id:"what-is-pundit",style:{position:"relative"}},t.createElement(e.a,{href:"#what-is-pundit","aria-label":"what is pundit permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"What is Pundit?"),"\n",t.createElement(e.p,null,t.createElement(e.a,{href:"https://github.com/varvet/pundit"},"Pundit"),"\nis a Ruby gem that provides a set of helpers\nand\nconventions for managing authorization in Rails applications.\nUnlike other authorization libraries,\nsuch as CanCanCan,\nPundit takes a different approach by focusing on policy objects.\nThese policy objects encapsulate the authorization logic\nfor a particular resource\nor\nmodel,\nkeeping the code organized\nand\neasy to maintain."),"\n",t.createElement(e.h2,{id:"key-features-of-pundit",style:{position:"relative"}},t.createElement(e.a,{href:"#key-features-of-pundit","aria-label":"key features of pundit permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Key Features of Pundit:"),"\n",t.createElement(e.ul,null,"\n",t.createElement(e.li,null,"\n",t.createElement(e.p,null,t.createElement(e.strong,null,"Clarity:"),"\nDefines authorization logic in clear,\nconcise Ruby classes,\nmaking it easier to understand\nand\nmaintain."),"\n"),"\n",t.createElement(e.li,null,"\n",t.createElement(e.p,null,t.createElement(e.strong,null,"Flexibility:"),"\nSupports various authorization scenarios,\nincluding CRUD operations,\ncustom actions,\nand\ncomplex permission structures."),"\n"),"\n",t.createElement(e.li,null,"\n",t.createElement(e.p,null,t.createElement(e.strong,null,"Testability:"),"\nEncourages writing unit tests for policies,\nensuring your authorization logic is robust\nand\nreliable."),"\n"),"\n",t.createElement(e.li,null,"\n",t.createElement(e.p,null,t.createElement(e.strong,null,"Integration:"),"\nIntegrates seamlessly with Rails controllers\nand\nviews,\nproviding helper methods for convenient authorization checks."),"\n"),"\n",t.createElement(e.li,null,"\n",t.createElement(e.p,null,t.createElement(e.strong,null,"Community:"),"\nBacked by a vibrant community with extensive documentation\nand\nresources."),"\n"),"\n"),"\n",t.createElement(e.h2,{id:"getting-started-with-pundit",style:{position:"relative"}}
1,t.createElement(e.a,{href:"#getting-started-with-pundit","aria-label":"getting started with pundit permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Getting Started with Pundit"),"\n",t.createElement(e.p,null,"Create a new Rails application by executing the below command:"),"\n",t.createElement(e.h3,{id:"create-a-new-rails-app-and-install-pundit",style:{position:"relative"}},t.createElement(e.a,{href:"#create-a-new-rails-app-and-install-pundit","aria-label":"create a new rails app and install pundit permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Create a new Rails app and install Pundit"),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token operator">></span> rails <span class="token keyword">new</span> demo_pundit</code></pre></div>'}}),"\n",t.createElement(e.p,null,"Navigate to the project\nand\nadd ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">pundit</code>'}})," gem to the project."),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token operator">></span> cd demo_pundit\n\n<span class="token operator">></span> bundle add pundit</code></pre></div>'}}),"\n",t.createElement(e.p,null,"You need to add ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">Pundit::Authorization</code>'}})," in your application controller."),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token keyword">class</span> <span class="token class-name">ApplicationController</span> <span class="token operator"><</span> ActionController<span class="token double-colon punctuation">::</span>Base\n <span class="token keyword">include</span> Pundit<span class="token double-colon punctuation">::</span>Authorization\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(e.p,null,"You can quickly run the generator to set up an\napplication policy with pre-configured defaults."),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token operator">></span> rails g pundit<span class="token symbol">:install</span>\n\n create app<span class="token operator">/</span>policies<span class="token operator">/</span>application_policy<span class="token punctuation">.</span>rb</code></pre></div>'}}),"\n",t.createElement(e.p,null,"The generator command created an ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">app/policies/</code>'}})," directory with a\nfile ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">application_policy.rb</code>'}})," inside."),"\n",t.createElement(e.h3,{id:"create-model",style:{position:"relative"}}
1,t.createElement(e.a,{href:"#create-model","aria-label":"create model permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Create model"),"\n",t.createElement(e.p,null,"Let's create a ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">User</code>'}})," model using the\n",t.createElement(e.a,{href:"https://github.com/heartcombo/devise"},"devise"),"\ngem."),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token operator">></span> bundle add devise\n\n<span class="token operator">></span> rails g devise<span class="token symbol">:install</span>\n\n<span class="token operator">></span> rails g devise user\n\n<span class="token operator">></span> rake db<span class="token symbol">:migrate</span></code></pre></div>'}}),"\n",t.createElement(e.h3,{id:"adding-policies",style:{position:"relative"}},t.createElement(e.a,{href:"#adding-policies","aria-label":"adding policies permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Adding policies"),"\n",t.createElement(e.p,null,"When we executed the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">rails g pundit:install</code>'}})," command,\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">application_policy.rb</code>'}})," was created.\nIt contains the below code:"),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token comment"># frozen_string_literal: true</span>\n\n<span class="token keyword">class</span> <span class="token class-name">ApplicationPolicy</span>\n attr_reader <span class="token symbol">:user</span><span class="token punctuation">,</span> <span class="token symbol">:record</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">initialize</span></span><span class="token punctuation">(</span>user<span class="token punctuation">,</span> record<span class="token punctuation">)</span>\n <span class="token variable">@user</span> <span class="token operator">=</span> user\n <span class="token variable">@record</span> <span class="token operator">=</span> record\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">index</span></span><span class="token operator">?</span>\n <span class="token boolean">false</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">show</span></span><span class="token operator">?</span>\n <span class="token boolean">false</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">create</span></span><span class="token operator">?</span>\n <span class="token boolean">
1false</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">new</span></span><span class="token operator">?</span>\n create<span class="token operator">?</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">update</span></span><span class="token operator">?</span>\n <span class="token boolean">false</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">edit</span></span><span class="token operator">?</span>\n update<span class="token operator">?</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">destroy</span></span><span class="token operator">?</span>\n <span class="token boolean">false</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">class</span> <span class="token class-name">Scope</span>\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">initialize</span></span><span class="token punctuation">(</span>user<span class="token punctuation">,</span> scope<span class="token punctuation">)</span>\n <span class="token variable">@user</span> <span class="token operator">=</span> user\n <span class="token variable">@scope</span> <span class="token operator">=</span> scope\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">resolve</span></span>\n <span class="token keyword">raise</span> NotImplementedError<span class="token punctuation">,</span> <span class="token string-literal"><span class="token string">"You must define #resolve in </span><span class="token interpolation"><span class="token delimiter punctuation">#{</span><span class="token content"><span class="token keyword">self</span><span class="token punctuation">.</span><span class="token keyword">class</span></span><span class="token delimiter punctuation">}</span></span><span class="token string">"</span></span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">private</span>\n\n attr_reader <span class="token symbol">:user</span><span class="token punctuation">,</span> <span class="token symbol">:scope</span>\n <span class="token keyword">end</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(e.p,null,"The model object is called a ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">record</code>'}})," in the above ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">ApplicationPolicy</code>'}})," file."),"\n",t.createElement(e.p,null,"Pundit's ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">ApplicationPolicy</code>'}})," defines\ncore authorization principles for your entire Rails application.\nIt is the starting point for all other policy classes,\noffering several benefits like ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">Default Permissions</code>'}}),",\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">Inheritance</code>'}}),",\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">Scopes</code>'}}),"\nand\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">Flexibility</code>'}}),"."),"\n",t.createElement(e.p,null,"The most common\nand\ngeneric permissions can be defined in the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">ApplicationPolicy</code>'}}),".\nYou can override methods in specific policies to\nhave granular control over models\nor\nactions."),"\n",t.createElement(e.p,null,"To have more control over User creation,\nupdation\nand\ndeletion,\nyou can create a ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">UserPolicy</code>'}})," using the pundit generator as below:"),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token operator">></span> rails generate pundit<span class="token symbol">:policy</span> User\n\n create app<span class="token operator">/</span>policies<span class="token operator">/</span>user_policy<span class="token punctuation">.</span>rb\n invoke test_unit\n create test<span class="token operator">/</span>policies<span class="token operator">/</span>user_policy_test<span class="token punctuation">.</span>rb</code></pre></div>'}}),"\n",t.createElement(e.p,null,"You want to ensure only admins in your application\ncan create new users\nand\ndestroy existing ones.\nYou can modify the method ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">create?</code>'}}),"\nand\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">destroy?</code>'}})," in the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">user_policy.rb</code>'}})," file."),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token keyword">class</span> <span class="token class-name">UserPolicy</span> <span class="token operator"><</span> ApplicationPolicy\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">create</span></span><span class="token operator">?</span>\n user<span class="token punctuation">.</span>admin<span class="token operator">?</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">destroy</span></span><span class="token operator">?</span>\n user<span class="token punctuation">.</span>admin<span class="token operator">?</span>\n <span class="token keyword">end</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(e.p,null,"To access these checks in your controller,\nyou need to add the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">authorize</code>'}})," method in your respective action\nas follows:"),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token keyword">class</span> <span class="token class-name">UsersController</span> <span class="token operator"><</span> ApplicationController\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">create</span></span>\n <span class="token variable">@user</span> <span class="token operator">=</span> <span class="token class-name">User</span><span class="token punctuation">.</span><span class="token keyword">new</span><span class="token punctuation">(</span>user_params<span class="token punctuation">)</span>\n authorize <span class="token variable">@user</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">destroy</span></span>\n <span class="token variable">@user</span> <span class="token operator">=</span> User<span class="token punctuation">.</span>find<span class="token punctuation">(</span>params<span class="token punctuation">[</span><span class="token symbol">:id</span><span class="token punctuation">]</span><span class="token punctuation">)</span>\n authorize <span class="token variable">@user</span>\n <span class="token keyword">end</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(e.p,null,"Behind the scenes,\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">authorize</code>'}})," simplifies authorization.\nIt automatically assumes a ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">User</code>'}})," model has a corresponding ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">UserPolicy</code>'}})," class.\nIt then instantiates the policy with the current user\nand\nthe specific ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">User</code>'}})," object.\nIt leverages the action name (e.g., ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">create</code>'}}),") to call the\nappropriate policy method ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">create?</code>'}}),"."),"\n",t.createElement(e.p,null,"If the action name does not match the policy function name,\nyou can pass an additional argument to the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">authorize</code>'}})," method."),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token keyword">def</span> <span class="token method-definition"><span class="token function">deactivate</span></span>\n <span class="token variable">@user</span> <span class="token operator">=</span> User<span class="token punctuation">.</span>find<span class="token punctuation">(</span>params<span class="token punctuation">[</span><span class="token symbol">:id</span><span class="token punctuation">]</span><span class="token punctuation">)</span>\n authorize <span class="token variable">@user</span><span class="token punctuation">,</span> <span class="token symbol">:update?</span>\n\n <span class="token variable">@user</span><span class="token punctuation">.</span>deactivate<span class="token operator">!</span>\n redirect_to <span class="token variable">@user</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(e.p,null,"When the first argument to authorize isn't an object,\nyou can pass the model class directly."),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token comment"># app/policies/user_policy.rb</span>\n\n<span class="token keyword">class</span> <span class="token class-name">UserPolicy</span> <span class="token operator"><</span> ApplicationPolicy\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">admins</span></span><span class="token operator">?</span>\n user<span class="token punctuation">.</span>admin<span class="token operator">?</span>\n <span class="token keyword">end</span>\n<span class="token keyword">end</span>\n\n<span class="token comment"># app/controllers/users_controller.rb</span>\n\n<span class="token keyword">class</span> <span class="token class-name">UsersController</span> <span class="token operator"><</span> ApplicationController\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">admins</span></span>\n authorize User\n <span class="token keyword">end</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(e.h3,{id:"using-policy-in-views",style:{position:"relative"}}
1,t.createElement(e.a,{href:"#using-policy-in-views","aria-label":"using policy in views permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Using policy in views"),"\n",t.createElement(e.p,null,"You can access a policy instance in both views\nand\ncontrollers using the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">policy</code>'}})," method.\nThis feature is precious for conditionally displaying links\nor\nbuttons in the view:"),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="erb"><pre class="language-erb"><code class="language-erb"><span class="token erb language-erb"><span class="token delimiter punctuation"><%</span><span class="token ruby language-ruby"> <span class="token keyword">if</span> policy<span class="token punctuation">(</span><span class="token variable">@user</span><span class="token punctuation">)</span><span class="token punctuation">.</span>update<span class="token operator">?</span> </span><span class="token delimiter punctuation">%></span></span>\n <span class="token erb language-erb"><span class="token delimiter punctuation"><%=</span><span class="token ruby language-ruby"> link_to <span class="token string-literal"><span class="token string">"Edit User"</span></span><span class="token punctuation">,</span> edit_user_path<span class="token punctuation">(</span><span class="token variable">@user</span><span class="token punctuation">)</span> </span><span class="token delimiter punctuation">%></span></span>\n<span class="token erb language-erb"><span class="token delimiter punctuation"><%</span><span class="token ruby language-ruby"> <span class="token keyword">end</span> </span><span class="token delimiter punctuation">%></span></span></code></pre></div>'}}),"\n",t.createElement(e.h3,{id:"scopes",style:{position:"relative"}},t.createElement(e.a,{href:"#scopes","aria-label":"scopes permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Scopes"),"\n",t.createElement(e.p,null,"Pundit does not have built-in support for\ndefining scopes within policy files.\nHowever,\nyou can still use Pundit in conjunction with ActiveRecord scopes\nto achieve the desired behaviour."),"\n",t.createElement(e.p,null,"Let's say you add a ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">Post</code>'}})," model to your Rails application.\nA user can create\nor\npublish many posts.\nYou can restrict access to the posts in your system\nby adding a Scope class in Pundit.\nHere's a basic example of\nhow you might use a scope in combination with Pundit."),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token comment"># app/policies/post_policy.rb</span>\n<span class="token keyword">class</span> <span class="token class-name">PostPolicy</span> <span class="token operator"><</span> ApplicationPolicy\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">index</span></span><span class="token operator">?</span>\n <span class="token boolean">true</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">class</span> <span class="token class-name">Scope</span>\n attr_reader <span class="token symbol">:user</span><span class="token punctuation">,</span> <span class="token symbol">:scope</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">initialize</span></span><span class="token punctuation">(</span>user<span class="token punctuation">,</span> scope<span class="token punctuation">)</span>
1\n <span class="token variable">@user</span> <span class="token operator">=</span> user\n <span class="token variable">@scope</span> <span class="token operator">=</span> scope\n <span class="token keyword">end</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">resolve</span></span>\n <span class="token keyword">if</span> user<span class="token punctuation">.</span>admin<span class="token operator">?</span>\n scope<span class="token punctuation">.</span>all\n <span class="token keyword">else</span>\n scope<span class="token punctuation">.</span>where<span class="token punctuation">(</span><span class="token symbol">user_id</span><span class="token operator">:</span> user<span class="token punctuation">.</span>id<span class="token punctuation">)</span>\n <span class="token keyword">end</span>\n <span class="token keyword">end</span>\n <span class="token keyword">end</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(e.p,null,"In this example,\nthe ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">Scope</code>'}})," class within the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">PostPolicy</code>'}})," defines a ",t.createElement(e.strong,null,"resolve")," method,\nwhich returns a scoped relation based on the user's role.\nIf the user is an ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">admin</code>'}}),",\nthey have access to all posts (",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">scope.all</code>'}}),");\notherwise,\nthey only have access to posts that belong to them (",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">scope.where(user_id: user.id)</code>'}}),")."),"\n",t.createElement(e.p,null,"In your controller,\nyou would use the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">policy_scope</code>'}})," method to apply the scope defined in your policy:"),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token keyword">class</span> <span class="token class-name">PostsController</span> <span class="token operator"><</span> ApplicationController\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">index</span></span>\n <span class="token variable">@posts</span> <span class="token operator">=</span> policy_scope<span class="token punctuation">(</span>Post<span class="token punctuation">)</span>\n <span class="token keyword">end</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(e.p,null,"The ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">policy_scope(Post)</code>'}})," call in the controller will apply the\nscope defined in the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">PostPolicy::Scope</code>'}})," class to the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">Post</code>'}})," model,\nensuring that only authorized records are returned."),"\n",t.createElement(e.p,null,"This approach allows you to use Pundit for authorization logic\nand\nActiveRecord scopes for record-level restrictions,\nprov
1iding a flexible\nand\npowerful way to manage access control in your Rails application."),"\n",t.createElement(e.h3,{id:"verifying-authorization-policy-and-scope-coverage",style:{position:"relative"}},t.createElement(e.a,{href:"#verifying-authorization-policy-and-scope-coverage","aria-label":"verifying authorization policy and scope coverage permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Verifying authorization policy and scope coverage"),"\n",t.createElement(e.p,null,"Unaddressed authorization checks in Pundit-powered a
1pplications\ncan create security vulnerabilities.\nThis emphasizes the importance of thoroughness from a security standpoint."),"\n",t.createElement(e.p,null,"Fortunately,\nPundit includes a helpful feature that serves as a reminder\nin case you overlook authorization.\nPundit keeps track of whether you have invoked ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">authorize</code>'}})," within your controller action.\nAdditionally,\nPundit adds a method called ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">verify_authorized</code>'}})," to your controllers.\nThis method will raise an exception if ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">authorize</code>'}})," has not been called.\nTo ensure you remember to ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">authorize</code>'}})," the action,\nyou should invoke this method in an ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">after_action</code>'}})," hook, as shown."),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token keyword">class</span> <span class="token class-name">ApplicationController</span> <span class="token operator"><</span> ActionController<span class="token double-colon punctuation">::</span>Base\n <span class="token keyword">include</span> Pundit<span class="token double-colon punctuation">::</span>Authorization\n after_action <span class="token symbol">:verify_authorized</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(e.p,null,"Similarly,\nPundit also introduces ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">verify_policy_scoped</code>'}})," to your controller.\nThis method functions similarly to ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">verify_authorized</code>'}}),"\nbut monitors the use of ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">policy_scope</code>'}})," instead of ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">authorize</code>'}}),".\nThis is particularly valuable for controller actions such as ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">index</code>'}}),",\nwhich retrieve collections with a scope\nand\ndo not authorize individual instances."),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token keyword">class</span> <span class="token class-name">ApplicationController</span> <span class="token operator"><</span> ActionController<span class="token double-colon punctuation">::</span>Base\n <span class="token keyword">include</span> Pundit<span class="token double-colon punctuation">::</span>Authorization\n after_action <span class="token symbol">:verify_authorized</span><span class="token punctuation">,</span> <span class="token symbol">except</span><span class="token operator">:</span> <span class="token symbol">:index</span>\n after_action <span class="token symbol">:verify_policy_scoped</span><span class="token punctuation">,</span> <span class="token symbol">only</span><span class="token operator">:</span> <span class="token symbol">:index</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(e.h3,{id:"strong-parameters",style:{position:"relative"}},t.createElement(e.a,{href:"#strong-parameters","aria-label":"strong parameters permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Strong parameters"),"\n",t.createElement(e.p,null,"In Rails,\nthe controller manages mass-assignment protection.\nHowever,\nwith Pundit,\nyou can determine which attributes a user can update by\ndefining rules in your policies.\nTo achieve this,\nyou can create a ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">permitted_attributes</code>'}})," method in your policy."),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token comment"># app/policies/post_policy.rb</span>\n\n<span class="token keyword">class</span> <span class="token class-name">PostPolicy</span> <span class="token operator"><</span> ApplicationPolicy\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">permitted_attributes</span></span>\n <span class="token keyword">if</span> user<span class="token punctuation">.</span>admin<span class="token operator">?</span> <span class="token operator">||</span> user<span class="token punctuation">.</span>author_of<span class="token operator">?</span><span class="token punctuation">(</span>record<span class="token punctuation">)</span>
1\n <span class="token punctuation">[</span><span class="token symbol">:title</span><span class="token punctuation">,</span> <span class="token symbol">:body</span><span class="token punctuation">,</span> <span class="token symbol">:categories</span><span class="token punctuation">]</span>\n <span class="token keyword">else</span>\n <span class="token punctuation">[</span><span class="token symbol">:categories</span><span class="token punctuation">]</span>\n <span class="token keyword">end</span>\n <span class="token keyword">end</span>\n<span class="token keyword">end</span></code></pre></div>'}}),"\n",t.createElement(e.p,null,"You need to call the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">permitted_attributes</code>'}})," of the ",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<code class="language-text">PostPolicy</code>'}}),"\nin your controller as below:"),"\n",t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<div class="gatsby-highlight" data-language="ruby"><pre class="language-ruby"><code class="language-ruby"><span class="token comment"># app/controllers/posts_controller.rb</span>\n\n<span class="token keyword">class</span> <span class="token class-name">PostsController</span> <span class="token operator"><</span> ApplicationController\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">update</span></span>\n <span class="token variable">@post</span> <span class="token operator">=</span> Post<span class="token punctuation">.</span>find<span class="token punctuation">(</span>params<span class="token punctuation">[</span><span class="token symbol">:id</span><span class="token punctuation">]</span><span class="token punctuation">)</span>\n <span class="token variable">@post</span><span class="token punctuation">.</span>update<span class="token punctuation">(</span>post_params<span class="token punctuation">)</span>\n <span class="token keyword">end</span>\n\n <span class="token keyword">private</span>\n\n <span class="token keyword">def</span> <span class="token method-definition"><span class="token function">post_params</span></span>\n params<span class="token punctuation">.</span>\n <span class="token keyword">require</span><span class="token punctuation">(</span><span class="token symbol">:post</span><span class="token punctuation">)</span><span class="token punctuation">.</span>\n permit<span class="token punctuation">(</span>policy<span class="token punctuation">(</span><span class="token variable">@post</span><span class="token punctuation">)</span><span class="token punctuation">.</span>permitted_attributes<span class="token punctuation">)</span>\n <span class="token keyword">end</span>\n<span class="token keyword">end</span></code></pre></div>'}}
1),"\n",t.createElement(e.h2,{id:"benefits-of-using-pundit",style:{position:"relative"}},t.createElement(e.a,{href:"#benefits-of-using-pundit","aria-label":"benefits of using pundit permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Benefits of Using Pundit:"),"\n",t.createElement(e.ul,null,"\n",t.createElement(e.li,null,t.createElement(e.strong,null,"Improved Code Quality:"),"\nPundit's object-oriented approach leads to cleaner,\nmore maintainable code."),"\n",t.createElement(e.li,null,t.createElement(e.strong,null,"Enhanced Security:"),"\nExplicitly defining authorization logic reduces the risk of security vulnerabilities."),"\n",t.createElement(e.li,null,t.createElement(e.strong,null,"Increased Developer Productivity:"),"\nClear policies\nand\nhelper methods simplify authorization checks."),"\n",t.createElement(e.li,null,t.createElement(e.strong,null,"Scalability:"),"\nPundit adapts well to complex applications with evolving authorization requirements."),"\n"),"\n",t.createElement(e.h2,{id:"conclusion",style:{position:"relative"}},t.createElement(e.a,{href:"#conclusion","aria-label":"conclusion permalink",className:"anchor before"},t.createElement(e.span,{dangerouslySetInnerHTML:{__html:'<svg aria-hidden="true" height="20" version="1.1" viewBox="0 0 16 16" width="20"><path fill-rule="evenodd" d="M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z"></path></svg>'}})),"Conclusion"),"\n",t.createElement(e.p,null,t.createElement(e.a,{href:"https://github.com/varvet/pundit"},"Pundit"),"\nis a powerful\nand\nflexible authorization library for Rails that simplifies\nthe process of implementing authorization logic in your application.\nBy using policy objects\nand\nconventions,\nPundit helps you keep your authorization code organized\nand\nmaintainable.\nWhether you're building a small web application\nor\na large-scale platform,\nPundit can help you manage authorization effectively\nand\nsecurely."))}var l=function(n){void 0===n&&(n={});const{wrapper:e}=Object.assign({},(0,s.R)(),n.components);return e?t.createElement(e,n,t.createElement(o,n)):o(n)},c=a(5588),p=a(65427),r=a(20504),i=a(43397),d=a(61942);const u=n=>n.replace(/\/+$/,""),h=(n,e)=>e?""+n+(e.startsWith("/")?e:"/"+e):n,m=(n,e)=>h(u(n),e),g=(n,e)=>h((n=>"undefined"!=typeof window?window.location.origin:u(n))(n),e),k=(n,e)=>{const a=(0,c.d)(e);return a?m(n,a):(n=>m(n,"/shakacode-og.png"))(n)},y=n=>{let{data:e,location:a,children:s}=n;const{frontmatter:o}=e.mdx,{siteUrl:l}=e.site.siteMetadata,c=g(l,a.pathname);return t.createElement(t.Fragment,null,t.createElement(p.A,null),t.createElement(r.A,{header:t.createElement(d.r,{breadcrumb:o.title}),main:t.createElement(t.Fragment,null,t.createElement(d.c,{body:s,title:o.title,author:o.author,date:o.date,link:c,categories:o.categories,featuredImage:o.featuredImage,showFeaturedImage:o.showFeaturedImage}),t.createElement(i.LN,null))}))};function b(n){return t.createElement(y,n,t.createElement(l,n))}const f=n=>{let{data:e,location:a}=n;const{frontmatter:s,excerpt:o}=e.mdx,{siteMetadata:l}=e.site,{siteUrl:c,title:p,description:r}=l,i=((n,e,a)=>n.excerpt||e||a)(s,o,r),d=k(c,s.featuredImage),u=m(c,a.pathname);return t.createElement(t.Fragment,null,t.createElement("title",null,s.title+" | "+p),t.createElement("link",{rel:"canonical",href:u}),t.createElement("meta",{name:"description",content:i}),t.createElement("meta",{property:"og:title",content:s.title}),t.createElement("meta",{property:"og:description",content:i}),t.createElement("meta",{property:"og:type",content:"article"}),t.createElement("meta",{property:"og:url",content:u}),t.createElement("meta",{property:"og:image",content:d}),t.createElement("meta",{name:"image",content:d}),t.createElement("meta",{name:"twitter:card",content:"summary_large_image"}),t.createElement("meta",{name:"twitter:title",content:s.title}),t.createElement("meta",{name:"twitter:description",content:i}),t.createElement("meta",{name:"twitter:image",content:d}))}}}]); 2//# sourceMappingURL=component---src-template-blog-article-tsx-content-file-path-src-posts-mastering-authorization-in-rails-with-pundit-index-mdx-64d05fcd4a998693fe17.js.map
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.