{"id":478192,"date":"2026-05-01T04:12:56","date_gmt":"2026-05-01T04:12:56","guid":{"rendered":"https:\/\/savepearlharbor.com\/?p=478192"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=478192","title":{"rendered":"\u041a\u0430\u043a \u00ab\u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439\u00bb Ruby-\u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0443\u043a\u0440\u0430\u043b request \u0438\u0437 Grape \u0438 \u043f\u043e\u043b\u043e\u043c\u0430\u043b \u043d\u0430\u043c Rate Limiting"},"content":{"rendered":"<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width \"><img decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e8c\/e9e\/5cc\/e8ce9e5cca22af459b317a8c98549158.png\" alt=\"\u041a\u0430\u043a &quot;\u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439&quot; Ruby-\u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0443\u043a\u0440\u0430\u043b request \u0438\u0437 Grape \u0438 \u043f\u043e\u043b\u043e\u043c\u0430\u043b \u043d\u0430\u043c Rate Limiting\" title=\"\u041a\u0430\u043a &quot;\u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439&quot; Ruby-\u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0443\u043a\u0440\u0430\u043b request \u0438\u0437 Grape \u0438 \u043f\u043e\u043b\u043e\u043c\u0430\u043b \u043d\u0430\u043c Rate Limiting\" width=\"2800\" height=\"1576\" sizes=\"auto, (max-width: 780px) 100vw, 50vw\" srcset=\"https:\/\/habrastorage.org\/r\/w780\/getpro\/habr\/upload_files\/e8c\/e9e\/5cc\/e8ce9e5cca22af459b317a8c98549158.png 780w,&#10;       https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/e8c\/e9e\/5cc\/e8ce9e5cca22af459b317a8c98549158.png 781w\" loading=\"lazy\" decode=\"async\"\/><\/p>\n<div><figcaption>\u041a\u0430\u043a &#171;\u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439&#187; Ruby-\u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0443\u043a\u0440\u0430\u043b request \u0438\u0437 Grape \u0438 \u043f\u043e\u043b\u043e\u043c\u0430\u043b \u043d\u0430\u043c Rate Limiting<\/figcaption><\/div>\n<\/figure>\n<p>\u0420\u0435\u0448\u0438\u043b\u0438 \u043c\u044b \u043a\u0430\u043a-\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c Rate Limits \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u043a <code>SubscriptionRequiredError<\/code> \u043e\u0448\u0438\u0431\u043a\u0430\u043c, \u0447\u0442\u043e\u0431\u044b \u0444\u0440\u043e\u043d\u0442 (\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u043a\u0430\u043b\u043e\u0440\u0438\u0439 <a href=\"https:\/\/mealup.org\" rel=\"noopener noreferrer nofollow\">MealUp<\/a>) \u043f\u043e\u043d\u0438\u043c\u0430\u043b, \u043a\u0430\u043a\u0438\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u043b\u0438\u043c\u0438\u0442\u044b \u0438 \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0441\u0442\u0430\u043b\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u044d\u0442\u0443 \u043e\u0448\u0438\u0431\u043a\u0443 \u0441 \u0440\u0430\u0441\u0447\u0451\u0442\u043e\u043c \u043b\u0438\u043c\u0438\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f &#8212; <code>current_user<\/code>. \u041f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u043b\u0438 \u043c\u044b \u043e\u0448\u0438\u0431\u043a\u0443 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e:<\/p>\n<p><strong>mealup\/app\/api\/v1\/api.rb:<\/strong><\/p>\n<pre><code class=\"ruby\">module V1  class API &lt; Grape::API    ...    rescue_from SubscriptionRequiredError, with: :render_error    ...    helpers V1::Helpers::ResponseHelpers    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:87px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p><strong>mealup\/app\/api\/v1\/helpers\/response_helpers.rb:<\/strong><\/p>\n<pre><code class=\"ruby\">module V1  module Helpers    module ResponseHelpers      ...      def render_error(error)        error = serialize_error(error)        error!({ error:, with: error_entity(error) }, error.try(:http_status) || 403)      end      def serialize_error(error)        case error        ...        when SubscriptionRequiredError          assign_rate_limit_headers(current_user, error.limit_key) # &lt;- \u0412\u043e\u0442 \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u043e\u0441\u044c          error        ...      end      ...          <\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0439\u0442\u0438 \u043d\u0435 \u0442\u0430\u043a? \u0410 \u0432\u043e\u0442 \u0432\u044b\u044f\u0441\u043d\u044f\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043d\u0435\u0442\u0443 \u0442\u0430\u043c <code>current_user<\/code>-\u0430. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e &#8212; \u0442\u0430\u043c \u043d\u0435\u0442 \u0434\u0430\u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 <code>request<\/code>, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u043c\u044b \u044d\u0442\u043e\u0433\u043e current_user-\u0430 \u0438 \u0438\u0449\u0435\u043c. &#171;\u041a\u0430\u043a \u0432 \u0430\u043f\u0438 \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430&#187;, &#8212; \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u0435 \u0432\u044b? &#171;\u041d\u0438\u043a\u0430\u043a&#187;, &#8212; \u043e\u0442\u0432\u0435\u0442\u0438\u043b \u0431\u044b \u044f. \u0418 \u0431\u044b\u043b \u0431\u044b \u043d\u0435\u043f\u0440\u0430\u0432.<\/p>\n<p>\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043e\u0431\u043b\u0438\u0436\u0435, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441 DSL Grape, \u0438 \u043a\u0443\u0434\u0430 \u0434\u0435\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0448 request. \u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0443 \u043d\u0430\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f gem &#8216;grape-swagger&#8217;, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 grape 2.2.0. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u0435\u043c \u044d\u0442\u0443 \u0432\u0435\u0440\u0441\u0438\u044e.<\/p>\n<p><code>:rescue_from<\/code> \u043c\u0435\u0442\u043e\u0434 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 <code>Grape::DSL::RequestResponse<\/code> (<code>lib\/grape\/dsl\/request_response.rb<\/code>). \u0422\u0430\u043c Grape \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0445 \u0432 <code>InheritableSetting<\/code>, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u0432 <code>Grape::Middleware::Error<\/code> \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u043a <code>:options<\/code>. \u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u043d\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:<\/p>\n<pre><code class=\"ruby\">options[:rescue_handlers]=&gt; {  ActiveRecord::RecordNotFound=&gt;:render_not_found_error,  SubscriptionRequiredError=&gt;:render_error,  Telegram::InvalidSchemeError=&gt;:render_error}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0442\u0443 \u0438\u043b\u0438 \u0438\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443, \u0437\u0430 \u044d\u0442\u043e \u0432\u043e\u0437\u044c\u043c\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 <code>Grape::Middleware::Error#run_rescue_handler<\/code>.<\/p>\n<pre><code class=\"ruby\">def run_rescue_handler(handler, error, endpoint)    if handler.instance_of?(Symbol)      raise NoMethodError, \"undefined method '#{handler}'\" unless respond_to?(handler)      handler = public_method(handler) # &lt;- \u0417\u0434\u0435\u0441\u044c \u0441\u0438\u043c\u0432\u043e\u043b :render_error \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 Method    end    ...    <\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0417\u0434\u0435\u0441\u044c handler \u0438\u0437 \u0441\u0438\u043c\u0432\u043e\u043b\u0430 <code>:render_error<\/code> \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 <code>Method<\/code>:<\/p>\n<pre><code class=\"bash\">handler=&gt; #&lt;Method: #&lt;Class:0x0000000123bf53c8&gt;(V1::Helpers::ResponseHelpers)#render_error(error) ...\/mealup\/app\/api\/v1\/helpers\/response_helpers.rb:59&gt;<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u0432 \u0442\u043e\u043c \u0436\u0435 <code>run_rescue_handler<\/code> \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d <code>endpoint.instance_exec(error, &amp;handler)<\/code>, \u0438 \u043a\u043e\u0434 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0438\u0437 \u0433\u0435\u043c\u0430 \u0432 \u043d\u0430\u0448 helper, \u043d\u043e \u0443\u0436\u0435 \u0431\u0435\u0437 <code>request<\/code> \u0438 \u0431\u0435\u0437 current_user.<\/p>\n<p>\u0410 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u0447\u0443\u0442\u044c \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u0443\u0435\u043c \u043a\u0440\u0430\u0441\u043e\u0442\u043e\u0439 \u0432 <code>api.rb<\/code>, \u0438 \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438, \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043b\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 \u043d\u0430 \u0442\u0440\u0435\u0445?<\/p>\n<pre><code class=\"ruby\"># rescue_from SubscriptionRequiredError, with: :render_errorrescue_from SubscriptionRequiredError do |e|  render_error(e)end<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 &#8212; \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435. \u041d\u043e \u0432\u043e\u0442 \u0433\u0434\u0435 \u043a\u0440\u043e\u0435\u0442\u0441\u044f \u043e\u0442\u043b\u0438\u0447\u0438\u0435:<\/p>\n<pre><code class=\"ruby\">options[:rescue_handlers]=&gt; {  ActiveRecord::RecordNotFound=&gt;:render_not_found_error,  SubscriptionRequiredError=&gt;#&lt;Proc:0x00000001259eb418 ...\/mealup\/app\/api\/v1\/api.rb:15&gt;,  Telegram::InvalidSchemeError=&gt;:render_error}<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0442\u0435\u043f\u0435\u0440\u044c \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 <code>run_rescue_handler<\/code> grape \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430\u0448 <code>handler<\/code> \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c <code>public_method(handler)<\/code>. \u041e\u043d \u0432\u043e\u0437\u044c\u043c\u0435\u0442 \u043d\u0430\u0448 \u0431\u043b\u043e\u043a \u0438\u043b\u0438 \u043b\u044f\u043c\u0431\u0434\u0443, \u0441\u043c\u043e\u0442\u0440\u044f, \u043a\u0430\u043a \u0432\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 <code>rescue_from<\/code> \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u0438 \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0441\u0442 \u0435\u0433\u043e \u0432 endpoint: <code>endpoint.instance_exec(error, &amp;handler)<\/code>. \u0418 \u0443\u0436\u0435 \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u0438\u0437 \u0433\u0435\u043c\u0430 \u0432 \u043d\u0430\u0448 helper \u0438 \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c <code>request<\/code>, \u0438 \u0441 <code>current_user<\/code>.<\/p>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u0436\u0435 \u0442\u0430\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442?<\/h3>\n<p>\u042d\u0442\u043e \u0443\u0436\u0435 \u043d\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c Grape, \u0430 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0441\u0430\u043c\u043e\u0433\u043e Ruby. \u0414\u0435\u043b\u043e \u0432 <code>instance_exec<\/code>, <code>Method<\/code>, <code>Proc<\/code> \u0438 \u0432 \u0442\u043e\u043c, \u043a\u0430\u043a \u043e\u043d\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0441 <code>self<\/code>, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442, \u043a\u0430\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u041e\u0431\u044a\u0435\u043a\u0442 <code>Method<\/code> &#8212; \u044d\u0442\u043e \u043c\u0435\u0442\u043e\u0434, \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 receiver-\u0443, \u043a\u0430\u043a\u043e\u043c\u0443-\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0443. \u0412 \u043d\u0435\u043c &#8212; <code>self<\/code> \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0432\u043d\u044b\u043c \u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0443. <code>Proc<\/code>, <code>block<\/code> \u0438 <code>lambda<\/code> &#8212; \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u0438 \u0432 \u044d\u0442\u043e\u043c \u0432\u043e\u043f\u0440\u043e\u0441\u0435, \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0441 <code>self<\/code>, \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u0437\u043e\u0432\u0430.<\/p>\n<p>\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u043f\u043e\u0447\u0435\u043c\u0443 <code>Method<\/code> \u0442\u0435\u0440\u044f\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u0430 \u043b\u044f\u043c\u0431\u0434\u0430 \u2014 \u043d\u0435\u0442, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043f\u0430\u0440\u0443 \u043a\u043b\u0430\u0441\u0441\u043e\u0432:<\/p>\n<pre><code class=\"ruby\">class Middleware  def greet    puts \"self is: #{self.class}\"    puts \"request: #{respond_to?(:request) ? request.inspect : 'NO METHOD request'}\"  endendclass Endpoint  attr_reader :request  def initialize    @request = \"I am the request object\"  end  def greet    puts \"self is: #{self.class}\"    puts \"request: #{respond_to?(:request) ? request.inspect : 'NO METHOD request'}\"  endend<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0418 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u0445 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b:<\/p>\n<pre><code class=\"ruby\">middleware = Middleware.newendpoint   = Endpoint.new<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u043b\u0438 \u043c\u044b \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043c\u0435\u0442\u043e\u0434 <code>:greet<\/code> \u0438\u0437 middleware \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u0435\u0433\u043e \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 endpoint, \u043a\u0430\u043a \u0432\u044b \u0434\u0443\u043c\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442? \u0423\u0432\u0438\u0434\u0438\u0442 \u043b\u0438 \u043e\u043d <code>@request<\/code>?<\/p>\n<pre><code class=\"bash\">irb(main):123&gt; handler = middleware.public_method(:greet)#&lt;Method: Middleware#greet() (irb):72&gt;irb(main):123&gt; endpoint.instance_exec(&amp;handler)self is: Middlewarerequest: NO METHOD request=&gt; nil<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0410 \u0435\u0441\u043b\u0438 handler \u0431\u0443\u0434\u0435\u0442 \u043b\u044f\u043c\u0431\u0434\u043e\u0439?<\/p>\n<pre><code class=\"bash\">irb(main):125&gt; handler = -&gt; { puts \"self is: #{self.class}\"; puts \"request: #{request.inspect}\" }=&gt; #&lt;Proc:0x000000012509ec98 (irb):125 (lambda)&gt;endpoint.instance_exec(&amp;handler)self is: Endpointrequest: \"I am the request object\"=&gt; nil<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438 \u0432 Grape. \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c <code>endpoint.instance_exec(error, &amp;handler)<\/code>, \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c handler \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 <code>Grape::Endpoint<\/code>:<\/p>\n<p><strong>gems\/grape-2.2.0\/lib\/grape\/endpoint.rb:<\/strong><\/p>\n<pre><code class=\"ruby\">...module Grape  # An Endpoint is the proxy scope in which all routing  # blocks are executed. In other words, any methods  # on the instance level of this class may be called  # from inside a `get`, `post`, etc.  class Endpoint    include Grape::DSL::Settings    include Grape::DSL::InsideRoute    attr_accessor :block, :source, :options    attr_reader :env, :request, :headers, :params # &lt;- \u043c\u0435\u0442\u043e\u0434 request \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442    ...<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041d\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 <code>Method<\/code> \u044d\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442. \u0415\u0441\u043b\u0438 \u043c\u044b \u0441\u0430\u043c\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u044d\u0442\u043e\u0442 handler \u0438\u0437 <code>Grape::Middleware::Error<\/code> (\u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0438\u0437 middleware-\u0446\u0435\u043f\u043e\u0447\u043a\u0438 proxy-\u043e\u0431\u044a\u0435\u043a\u0442\u0430 Grape), \u0442\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b <code>Grape::Endpoint<\/code>, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a <code>request<\/code>, \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u0443\u0436\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e, <code>Proc<\/code> \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441 <code>self<\/code>, \u0440\u0430\u0432\u043d\u044b\u043c <code>endpoint<\/code>, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442 <code>request<\/code> \u0442\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d. \u042d\u0442\u043e, \u043a\u0441\u0442\u0430\u0442\u0438, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0434\u0430\u0436\u0435 \u0438\u0437 \u0445\u0435\u043b\u043f\u0435\u0440\u0430 \u0432 MealUp:<\/p>\n<p><strong>mealup\/app\/api\/v1\/helpers\/response_helpers.rb:<\/strong><\/p>\n<pre><code class=\"ruby\">def serialize_error(error)  ...  when SubscriptionRequiredError    debugger # &lt;- \u0421\u0442\u0430\u0432\u0438\u043c debugger \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043c\u0435\u0441\u0442\u043e\u043c, \u0433\u0434\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0442\u0438 \u043e\u0448\u0438\u0431\u043a\u0430    assign_rate_limit_headers(current_user, error.limit_key)    error  ...end<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0415\u0441\u043b\u0438 <code>:rescue_from<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0441 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u043c:<\/p>\n<pre><code class=\"bash\">   70:         when SubscriptionRequiredError   71:           debugger=&gt; 72:           assign_rate_limit_headers(current_user, error.limit_key)   73:           error   74:         else   75:           error   76:         end(byebug) Grape::Middleware::Error === selftrue(byebug) Grape::Endpoint === selffalse<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u0415\u0441\u043b\u0438 <code>:rescue_from<\/code> \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0441 \u043b\u044f\u043c\u0431\u0434\u043e\u0439 \u0438\u043b\u0438 \u0431\u043b\u043e\u043a\u043e\u043c:<\/p>\n<pre><code class=\"bash\">   70:         when SubscriptionRequiredError   71:           debugger=&gt; 72:           assign_rate_limit_headers(current_user, error.limit_key)   73:           error   74:         else   75:           error   76:         end(byebug) Grape::Middleware::Error === selffalse(byebug) Grape::Endpoint === selftrue<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<p>\u041f\u0440\u043e\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u044f: <code>Proc<\/code> \u0431\u0435\u0440\u0451\u0442 <code>self<\/code> \u0438\u0437 \u043c\u0435\u0441\u0442\u0430 \u0432\u044b\u0437\u043e\u0432\u0430, \u0430 <code>Method<\/code> \u2014 \u0438\u0437 \u0441\u0432\u043e\u0435\u0433\u043e receiver\u2019\u0430<\/p>\n<h3>\u041f\u043e\u0447\u0435\u043c\u0443 \u043c\u044b \u043b\u044e\u0431\u0438\u043c Ruby<\/h3>\n<p>\u0427\u0442\u043e \u0436, \u043c\u044b \u043d\u0430\u0448\u043b\u0438 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u043e\u0444\u0438\u043a\u0441\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443. \u0422\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442, headers \u043e\u0442\u0431\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u0444\u0440\u043e\u043d\u0442 \u0438 \u0441 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u043c \u043e\u0442\u0432\u0435\u0442\u043e\u043c, \u0438 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439. \u041d\u0430\u0448\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0441\u043c\u043e\u0433\u0443\u0442 <a href=\"https:\/\/app.mealup.org\" rel=\"noopener noreferrer nofollow\">\u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043a\u0430\u043b\u043e\u0440\u0438\u0438 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e<\/a>, \u0438 \u0437\u043d\u0430\u0442\u044c, \u0432 \u043a\u0430\u043a\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430. \u041d\u043e \u0422\u0420\u0418 \u0441\u0442\u0440\u043e\u043a\u0438, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0434\u043d\u0443? \u0414\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e Ruby \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u044d\u0442\u043e \u0437\u0432\u0443\u0447\u0438\u0442 \u043a\u0430\u043a \u0432\u044b\u0437\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u0438\u043a\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0448\u0435\u043b \u0432 \u043f\u0440\u043e\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:<\/p>\n<p><strong>mealup\/app\/api\/v1\/api.rb:<\/strong><\/p>\n<pre><code class=\"ruby\">rescue_from SubscriptionRequiredError, with: -&gt;(e) { render_error(e) }<\/code><div class=\"code-explainer\"><a href=\"https:\/\/sourcecraft.dev\/\" class=\"tm-button code-explainer__link\" style=\"visibility: hidden;\"><img style=\"width:14px;height:14px;object-fit:cover;object-position:left;\"\/><\/a><\/div><\/pre>\n<h3>\u0412\u044b\u0432\u043e\u0434\u044b<\/h3>\n<p>1. \u0412 Grape <code>rescue_from<\/code> \u0441 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u043c (<code>with: :render_error<\/code>) \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 <code>Method<\/code>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 <strong>\u0436\u0451\u0441\u0442\u043a\u043e \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d<\/strong> \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443 \u0438\u0437 middleware-\u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u043d\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 <code>Grape::Endpoint<\/code>, \u0438\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u0442\u0435\u0440\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a <code>request<\/code>.<\/p>\n<p>2. <code>rescue_from<\/code> \u0441 \u0431\u043b\u043e\u043a\u043e\u043c \u0438\u043b\u0438 \u043b\u044f\u043c\u0431\u0434\u043e\u0439 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 <code>Grape::Endpoint<\/code> \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u0438 <code>Proc<\/code>.<\/p>\n<p>3. \u0415\u0441\u043b\u0438 \u0432\u0430\u0448 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a <code>request<\/code>, <code>params<\/code>, <code>current_user<\/code> \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u0430\u043c <code>Grape::Endpoint<\/code> \u2014 <strong>\u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043b\u044f\u043c\u0431\u0434\u0443 \u0438\u043b\u0438 \u0431\u043b\u043e\u043a<\/strong>.<\/p>\n<p>4. \u041a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439. \u0418\u043d\u043e\u0433\u0434\u0430 \u0437\u0430 \u043a\u0440\u0430\u0441\u043e\u0442\u043e\u0439 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u044c \u043c\u043d\u043e\u0433\u043e\u0447\u0430\u0441\u043e\u0432\u043e\u0433\u043e \u0434\u0435\u0431\u0430\u0433\u0430. (\u041d\u043e Ruby &#8212; \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043a\u043b\u0430\u0441\u0441\u043d\u044b\u0439).<\/p>\n<\/div>\n<p>\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/articles\/1030354\/\">https:\/\/habr.com\/ru\/articles\/1030354\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u041a\u0430\u043a &#171;\u043a\u0440\u0430\u0441\u0438\u0432\u044b\u0439&#187; Ruby-\u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u0443\u043a\u0440\u0430\u043b request \u0438\u0437 Grape \u0438 \u043f\u043e\u043b\u043e\u043c\u0430\u043b \u043d\u0430\u043c Rate Limiting\u0420\u0435\u0448\u0438\u043b\u0438 \u043c\u044b \u043a\u0430\u043a-\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c Rate Limits \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u043a SubscriptionRequiredError \u043e\u0448\u0438\u0431\u043a\u0430\u043c, \u0447\u0442\u043e\u0431\u044b \u0444\u0440\u043e\u043d\u0442 (\u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0434\u043b\u044f \u043f\u043e\u0434\u0441\u0447\u0435\u0442\u0430 \u043a\u0430\u043b\u043e\u0440\u0438\u0439 MealUp) \u043f\u043e\u043d\u0438\u043c\u0430\u043b, \u043a\u0430\u043a\u0438\u0435 \u0438\u043c\u0435\u043d\u043d\u043e \u043b\u0438\u043c\u0438\u0442\u044b \u0438 \u043d\u0430\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044c \u043f\u0440\u0435\u0432\u044b\u0441\u0438\u043b. \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u043c\u044b \u0441\u0442\u0430\u043b\u0438 \u0440\u0435\u043d\u0434\u0435\u0440\u0438\u0442\u044c \u044d\u0442\u0443 \u043e\u0448\u0438\u0431\u043a\u0443 \u0441 \u0440\u0430\u0441\u0447\u0451\u0442\u043e\u043c \u043b\u0438\u043c\u0438\u0442\u043e\u0432 \u0434\u043b\u044f \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u0433\u043e \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u044f &#8212; current_user. \u041f\u0435\u0440\u0435\u0445\u0432\u0430\u0442\u044b\u0432\u0430\u043b\u0438 \u043c\u044b \u043e\u0448\u0438\u0431\u043a\u0443 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u043d\u043e:mealup\/app\/api\/v1\/api.rb:module V1  class API &lt; Grape::API    &#8230;    rescue_from SubscriptionRequiredError, with: :render_error    &#8230;    helpers V1::Helpers::ResponseHelpers    &#8230;mealup\/app\/api\/v1\/helpers\/response_helpers.rb:module V1  module Helpers    module ResponseHelpers      &#8230;      def render_error(error)        error = serialize_error(error)        error!({ error:, with: error_entity(error) }, error.try(:http_status) || 403)      end      def serialize_error(error)        case error        &#8230;        when SubscriptionRequiredError          assign_rate_limit_headers(current_user, error.limit_key) # &lt;- \u0412\u043e\u0442 \u0447\u0442\u043e \u0434\u043e\u0431\u0430\u0432\u0438\u043b\u043e\u0441\u044c          error        &#8230;      end      &#8230;          \u041a\u0430\u0437\u0430\u043b\u043e\u0441\u044c \u0431\u044b, \u0447\u0442\u043e \u043c\u043e\u0436\u0435\u0442 \u043f\u043e\u0439\u0442\u0438 \u043d\u0435 \u0442\u0430\u043a? \u0410 \u0432\u043e\u0442 \u0432\u044b\u044f\u0441\u043d\u044f\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u043d\u0435\u0442\u0443 \u0442\u0430\u043c current_user-\u0430. \u0411\u043e\u043b\u0435\u0435 \u0442\u043e\u0433\u043e &#8212; \u0442\u0430\u043c \u043d\u0435\u0442 \u0434\u0430\u0436\u0435 \u043e\u0431\u044a\u0435\u043a\u0442\u0430 request, \u0438\u0437 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0447\u0435\u0440\u0435\u0437 \u0437\u0430\u0433\u043e\u043b\u043e\u0432\u043a\u0438 \u043c\u044b \u044d\u0442\u043e\u0433\u043e current_user-\u0430 \u0438 \u0438\u0449\u0435\u043c. &#171;\u041a\u0430\u043a \u0432 \u0430\u043f\u0438 \u043f\u0440\u0438 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u043a\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430 \u043c\u043e\u0436\u0435\u0442 \u043e\u0442\u0441\u0443\u0442\u0441\u0442\u0432\u043e\u0432\u0430\u0442\u044c \u043e\u0431\u044a\u0435\u043a\u0442 \u0437\u0430\u043f\u0440\u043e\u0441\u0430&#187;, &#8212; \u0441\u043f\u0440\u043e\u0441\u0438\u0442\u0435 \u0432\u044b? &#171;\u041d\u0438\u043a\u0430\u043a&#187;, &#8212; \u043e\u0442\u0432\u0435\u0442\u0438\u043b \u0431\u044b \u044f. \u0418 \u0431\u044b\u043b \u0431\u044b \u043d\u0435\u043f\u0440\u0430\u0432.\u041f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043f\u043e\u0431\u043b\u0438\u0436\u0435, \u0447\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0441 DSL Grape, \u0438 \u043a\u0443\u0434\u0430 \u0434\u0435\u0432\u0430\u0435\u0442\u0441\u044f \u043d\u0430\u0448 request. \u0412 \u043f\u0440\u043e\u0435\u043a\u0442\u0435 \u0443 \u043d\u0430\u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f gem &#8216;grape-swagger&#8217;, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 grape 2.2.0. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u0441\u0443\u0436\u0434\u0430\u0435\u043c \u044d\u0442\u0443 \u0432\u0435\u0440\u0441\u0438\u044e.:rescue_from \u043c\u0435\u0442\u043e\u0434 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u044f\u0435\u0442\u0441\u044f \u0432 Grape::DSL::RequestResponse (lib\/grape\/dsl\/request_response.rb). \u0422\u0430\u043c Grape \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442 \u043d\u0430\u0439\u0434\u0435\u043d\u043d\u044b\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u043e\u0448\u0438\u0431\u043e\u043a \u0438 \u0437\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u0435\u0442 \u0438\u0445 \u0432 InheritableSetting, \u043f\u043e\u0441\u043b\u0435 \u0447\u0435\u0433\u043e \u043e\u043d\u0438 \u0431\u0443\u0434\u0443\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u043d\u044b \u0432 Grape::Middleware::Error \u043f\u0440\u0438 \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u0438 \u043a\u0430\u043a :options. \u0417\u0430\u043f\u0438\u0441\u044b\u0432\u0430\u044e\u0442\u0441\u044f \u043e\u043d\u0438 \u043f\u0440\u0438\u043c\u0435\u0440\u043d\u043e \u0442\u0430\u043a:options[:rescue_handlers]=&gt; {  ActiveRecord::RecordNotFound=&gt;:render_not_found_error,  SubscriptionRequiredError=&gt;:render_error,  Telegram::InvalidSchemeError=&gt;:render_error}\u041a\u043e\u0433\u0434\u0430 \u043f\u043e\u043d\u0430\u0434\u043e\u0431\u0438\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0430\u0442\u044c \u0442\u0443 \u0438\u043b\u0438 \u0438\u043d\u0443\u044e \u043e\u0448\u0438\u0431\u043a\u0443, \u0437\u0430 \u044d\u0442\u043e \u0432\u043e\u0437\u044c\u043c\u0435\u0442\u0441\u044f \u043c\u0435\u0442\u043e\u0434 Grape::Middleware::Error#run_rescue_handler.def run_rescue_handler(handler, error, endpoint)    if handler.instance_of?(Symbol)      raise NoMethodError, &#171;undefined method &#8216;#{handler}'&#187; unless respond_to?(handler)      handler = public_method(handler) # &lt;- \u0417\u0434\u0435\u0441\u044c \u0441\u0438\u043c\u0432\u043e\u043b :render_error \u043f\u0440\u0435\u0432\u0440\u0430\u0442\u0438\u0442\u0441\u044f \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 Method    end    &#8230;    \u0417\u0434\u0435\u0441\u044c handler \u0438\u0437 \u0441\u0438\u043c\u0432\u043e\u043b\u0430 :render_error \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u043e\u0431\u044a\u0435\u043a\u0442 \u043a\u043b\u0430\u0441\u0441\u0430 Method:handler=&gt; #&lt;Method: #&lt;Class:0x0000000123bf53c8&gt;(V1::Helpers::ResponseHelpers)#render_error(error) &#8230;\/mealup\/app\/api\/v1\/helpers\/response_helpers.rb:59&gt;\u0447\u0443\u0442\u044c \u043f\u043e\u0437\u0436\u0435 \u0432 \u0442\u043e\u043c \u0436\u0435 run_rescue_handler \u0431\u0443\u0434\u0435\u0442 \u0432\u044b\u0437\u0432\u0430\u043d endpoint.instance_exec(error, &amp;handler), \u0438 \u043a\u043e\u0434 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0438\u0437 \u0433\u0435\u043c\u0430 \u0432 \u043d\u0430\u0448 helper, \u043d\u043e \u0443\u0436\u0435 \u0431\u0435\u0437 request \u0438 \u0431\u0435\u0437 current_user.\u0410 \u0447\u0442\u043e \u0435\u0441\u043b\u0438 \u043c\u044b \u0447\u0443\u0442\u044c \u043f\u043e\u0436\u0435\u0440\u0442\u0432\u0443\u0435\u043c \u043a\u0440\u0430\u0441\u043e\u0442\u043e\u0439 \u0432 api.rb, \u0438 \u0432\u043c\u0435\u0441\u0442\u043e \u043e\u0434\u043d\u043e\u0439 \u0441\u0442\u0440\u043e\u043a\u0438, \u0431\u0443\u0434\u0435\u043c \u043e\u0442\u043b\u0430\u0432\u043b\u0438\u0432\u0430\u0442\u044c \u043e\u0448\u0438\u0431\u043a\u0443 \u043d\u0430 \u0442\u0440\u0435\u0445?# rescue_from SubscriptionRequiredError, with: :render_errorrescue_from SubscriptionRequiredError do |e|  render_error(e)end\u041d\u0430 \u043f\u0435\u0440\u0432\u044b\u0439 \u0432\u0437\u0433\u043b\u044f\u0434 &#8212; \u0442\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435. \u041d\u043e \u0432\u043e\u0442 \u0433\u0434\u0435 \u043a\u0440\u043e\u0435\u0442\u0441\u044f \u043e\u0442\u043b\u0438\u0447\u0438\u0435:options[:rescue_handlers]=&gt; {  ActiveRecord::RecordNotFound=&gt;:render_not_found_error,  SubscriptionRequiredError=&gt;#&lt;Proc:0x00000001259eb418 &#8230;\/mealup\/app\/api\/v1\/api.rb:15&gt;,  Telegram::InvalidSchemeError=&gt;:render_error}\u0442\u0435\u043f\u0435\u0440\u044c \u0432 \u043c\u0435\u0442\u043e\u0434\u0435 run_rescue_handler grape \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u0434\u043c\u0435\u043d\u044f\u0442\u044c \u043d\u0430\u0448 handler \u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c public_method(handler). \u041e\u043d \u0432\u043e\u0437\u044c\u043c\u0435\u0442 \u043d\u0430\u0448 \u0431\u043b\u043e\u043a \u0438\u043b\u0438 \u043b\u044f\u043c\u0431\u0434\u0443, \u0441\u043c\u043e\u0442\u0440\u044f, \u043a\u0430\u043a \u0432\u044b \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 rescue_from \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a, \u0438 \u0442\u043e\u0447\u043d\u043e \u0442\u0430\u043a\u0436\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0441\u0442 \u0435\u0433\u043e \u0432 endpoint: endpoint.instance_exec(error, &amp;handler). \u0418 \u0443\u0436\u0435 \u0432 \u044d\u0442\u043e\u043c \u0441\u043b\u0443\u0447\u0430\u0435 \u043c\u044b \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u0441\u044f \u0438\u0437 \u0433\u0435\u043c\u0430 \u0432 \u043d\u0430\u0448 helper \u0438 \u0441 \u043e\u0431\u044a\u0435\u043a\u0442\u043e\u043c request, \u0438 \u0441 current_user.\u041f\u043e\u0447\u0435\u043c\u0443 \u0436\u0435 \u0442\u0430\u043a \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442?\u042d\u0442\u043e \u0443\u0436\u0435 \u043d\u0435 \u043e\u0441\u043e\u0431\u0435\u043d\u043d\u043e\u0441\u0442\u044c Grape, \u0430 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u0441\u0430\u043c\u043e\u0433\u043e Ruby. \u0414\u0435\u043b\u043e \u0432 instance_exec, Method, Proc \u0438 \u0432 \u0442\u043e\u043c, \u043a\u0430\u043a \u043e\u043d\u0438 \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u0441 self, \u043e\u0442 \u043a\u043e\u0442\u043e\u0440\u043e\u0433\u043e \u0437\u0430\u0432\u0438\u0441\u0438\u0442, \u043a\u0430\u043a\u0438\u0435 \u043c\u0435\u0442\u043e\u0434\u044b \u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u041e\u0431\u044a\u0435\u043a\u0442 Method &#8212; \u044d\u0442\u043e \u043c\u0435\u0442\u043e\u0434, \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d\u043d\u044b\u0439 \u043a \u043a\u043e\u043d\u043a\u0440\u0435\u0442\u043d\u043e\u043c\u0443 receiver-\u0443, \u043a\u0430\u043a\u043e\u043c\u0443-\u0442\u043e \u043e\u0431\u044a\u0435\u043a\u0442\u0443. \u0412 \u043d\u0435\u043c &#8212; self \u0432\u0441\u0435\u0433\u0434\u0430 \u0431\u0443\u0434\u0435\u0442 \u0440\u0430\u0432\u043d\u044b\u043c \u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442\u0443. Proc, block \u0438 lambda &#8212; \u0431\u043e\u043b\u0435\u0435 \u0433\u0438\u0431\u043a\u0438 \u0432 \u044d\u0442\u043e\u043c \u0432\u043e\u043f\u0440\u043e\u0441\u0435, \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u0441 self, \u0437\u0430\u0434\u0430\u043d\u043d\u044b\u043c \u0432 \u043c\u043e\u043c\u0435\u043d\u0442 \u0432\u044b\u0437\u043e\u0432\u0430.\u0427\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u043f\u043e\u0447\u0435\u043c\u0443 Method \u0442\u0435\u0440\u044f\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442, \u0430 \u043b\u044f\u043c\u0431\u0434\u0430 \u2014 \u043d\u0435\u0442, \u0434\u0430\u0432\u0430\u0439\u0442\u0435 \u043f\u043e\u0441\u043c\u043e\u0442\u0440\u0438\u043c \u043d\u0430 \u043f\u0440\u043e\u0441\u0442\u0435\u043d\u044c\u043a\u0438\u0439 \u043f\u0440\u0438\u043c\u0435\u0440. \u041e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043c \u043f\u0430\u0440\u0443 \u043a\u043b\u0430\u0441\u0441\u043e\u0432:class Middleware  def greet    puts &#171;self is: #{self.class}&#187;    puts &#171;request: #{respond_to?(:request) ? request.inspect : &#8216;NO METHOD request&#8217;}&#187;  endendclass Endpoint  attr_reader :request  def initialize    @request = &#171;I am the request object&#187;  end  def greet    puts &#171;self is: #{self.class}&#187;    puts &#171;request: #{respond_to?(:request) ? request.inspect : &#8216;NO METHOD request&#8217;}&#187;  endend\u0418 \u0441\u043e\u0437\u0434\u0430\u0434\u0438\u043c \u0438\u0445 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b:middleware = Middleware.newendpoint   = Endpoint.new\u0422\u0435\u043f\u0435\u0440\u044c \u0435\u0441\u043b\u0438 \u043c\u044b \u0432\u043e\u0437\u044c\u043c\u0435\u043c \u043c\u0435\u0442\u043e\u0434 :greet \u0438\u0437 middleware \u0438 \u043f\u0440\u0438\u043c\u0435\u043d\u0438\u043c \u0435\u0433\u043e \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 endpoint, \u043a\u0430\u043a \u0432\u044b \u0434\u0443\u043c\u0430\u0435\u0442\u0435, \u0447\u0442\u043e \u0431\u0443\u0434\u0435\u0442? \u0423\u0432\u0438\u0434\u0438\u0442 \u043b\u0438 \u043e\u043d @request?irb(main):123&gt; handler = middleware.public_method(:greet)#&lt;Method: Middleware#greet() (irb):72&gt;irb(main):123&gt; endpoint.instance_exec(&amp;handler)self is: Middlewarerequest: NO METHOD request=&gt; nil\u0410 \u0435\u0441\u043b\u0438 handler \u0431\u0443\u0434\u0435\u0442 \u043b\u044f\u043c\u0431\u0434\u043e\u0439?irb(main):125&gt; handler = -&gt; { puts &#171;self is: #{self.class}&#187;; puts &#171;request: #{request.inspect}&#187; }=&gt; #&lt;Proc:0x000000012509ec98 (irb):125 (lambda)&gt;endpoint.instance_exec(&amp;handler)self is: Endpointrequest: &#171;I am the request object&#187;=&gt; nil\u0422\u043e \u0436\u0435 \u0441\u0430\u043c\u043e\u0435 \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442 \u0438 \u0432 Grape. \u041a\u043e\u0433\u0434\u0430 \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c endpoint.instance_exec(error, &amp;handler), \u043c\u044b \u0432\u044b\u0437\u044b\u0432\u0430\u0435\u043c handler \u0432 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0435 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430 Grape::Endpoint:gems\/grape-2.2.0\/lib\/grape\/endpoint.rb:&#8230;module Grape  # An Endpoint is the proxy scope in which all routing  # blocks are executed. In other words, any methods  # on the instance level of this class may be called  # from inside a `get`, `post`, etc.  class Endpoint    include Grape::DSL::Settings    include Grape::DSL::InsideRoute    attr_accessor :block, :source, :options    attr_reader :env, :request, :headers, :params # &lt;- \u043c\u0435\u0442\u043e\u0434 request \u0437\u0434\u0435\u0441\u044c \u043f\u0440\u0438\u0441\u0443\u0442\u0441\u0442\u0432\u0443\u0435\u0442    &#8230;\u041d\u043e \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 Method \u044d\u0442\u043e \u043d\u0435 \u0441\u0440\u0430\u0431\u0430\u0442\u044b\u0432\u0430\u0435\u0442. \u0415\u0441\u043b\u0438 \u043c\u044b \u0441\u0430\u043c\u0438 \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0438\u043b\u0438 \u044d\u0442\u043e\u0442 handler \u0438\u0437 Grape::Middleware::Error (\u043d\u0430 \u0441\u0430\u043c\u043e\u043c \u0434\u0435\u043b\u0435, \u0438\u0437 middleware-\u0446\u0435\u043f\u043e\u0447\u043a\u0438 proxy-\u043e\u0431\u044a\u0435\u043a\u0442\u0430 Grape), \u0442\u043e \u0430\u0442\u0440\u0438\u0431\u0443\u0442\u044b Grape::Endpoint, \u0442\u0430\u043a\u0438\u0435 \u043a\u0430\u043a request, \u0434\u043b\u044f \u043d\u0435\u0433\u043e \u0443\u0436\u0435 \u043d\u0435\u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b. \u0412 \u043e\u0442\u043b\u0438\u0447\u0438\u0435 \u043e\u0442 \u044d\u0442\u043e\u0433\u043e, Proc \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0441 self, \u0440\u0430\u0432\u043d\u044b\u043c endpoint, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043e\u0431\u044a\u0435\u043a\u0442 request \u0442\u0430\u043c \u0431\u0443\u0434\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f\u0435\u043d. \u042d\u0442\u043e, \u043a\u0441\u0442\u0430\u0442\u0438, \u043c\u043e\u0436\u043d\u043e \u043f\u0440\u043e\u0432\u0435\u0440\u0438\u0442\u044c \u0434\u0430\u0436\u0435 \u0438\u0437 \u0445\u0435\u043b\u043f\u0435\u0440\u0430 \u0432 MealUp:mealup\/app\/api\/v1\/helpers\/response_helpers.rb:def serialize_error(error)  &#8230;  when SubscriptionRequiredError    debugger # &lt;- \u0421\u0442\u0430\u0432\u0438\u043c debugger \u043f\u0435\u0440\u0435\u0434 \u0442\u0435\u043c \u043c\u0435\u0441\u0442\u043e\u043c, \u0433\u0434\u0435 \u0434\u043e\u043b\u0436\u043d\u0430 \u043f\u0440\u043e\u0438\u0437\u043e\u0439\u0442\u0438 \u043e\u0448\u0438\u0431\u043a\u0430    assign_rate_limit_headers(current_user, error.limit_key)    error  &#8230;end\u0415\u0441\u043b\u0438 :rescue_from \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0441 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u043c:   70:         when SubscriptionRequiredError   71:           debugger=&gt; 72:           assign_rate_limit_headers(current_user, error.limit_key)   73:           error   74:         else   75:           error   76:         end(byebug) Grape::Middleware::Error === selftrue(byebug) Grape::Endpoint === selffalse\u0415\u0441\u043b\u0438 :rescue_from \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d \u0441 \u043b\u044f\u043c\u0431\u0434\u043e\u0439 \u0438\u043b\u0438 \u0431\u043b\u043e\u043a\u043e\u043c:   70:         when SubscriptionRequiredError   71:           debugger=&gt; 72:           assign_rate_limit_headers(current_user, error.limit_key)   73:           error   74:         else   75:           error   76:         end(byebug) Grape::Middleware::Error === selffalse(byebug) Grape::Endpoint === selftrue\u041f\u0440\u043e\u0449\u0435 \u0433\u043e\u0432\u043e\u0440\u044f: Proc \u0431\u0435\u0440\u0451\u0442 self \u0438\u0437 \u043c\u0435\u0441\u0442\u0430 \u0432\u044b\u0437\u043e\u0432\u0430, \u0430 Method \u2014 \u0438\u0437 \u0441\u0432\u043e\u0435\u0433\u043e receiver\u2019\u0430\u041f\u043e\u0447\u0435\u043c\u0443 \u043c\u044b \u043b\u044e\u0431\u0438\u043c Ruby\u0427\u0442\u043e \u0436, \u043c\u044b \u043d\u0430\u0448\u043b\u0438 \u0441\u043f\u043e\u0441\u043e\u0431 \u043f\u043e\u0444\u0438\u043a\u0441\u0438\u0442\u044c \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0443. \u0422\u0435\u0441\u0442\u044b \u043f\u0440\u043e\u0445\u043e\u0434\u044f\u0442, headers \u043e\u0442\u0431\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043d\u0430 \u0444\u0440\u043e\u043d\u0442 \u0438 \u0441 \u0443\u0441\u043f\u0435\u0448\u043d\u044b\u043c \u043e\u0442\u0432\u0435\u0442\u043e\u043c, \u0438 \u0441 \u043e\u0448\u0438\u0431\u043a\u043e\u0439. \u041d\u0430\u0448\u0438 \u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u0435\u043b\u0438 \u0441\u043c\u043e\u0433\u0443\u0442 \u0441\u0447\u0438\u0442\u0430\u0442\u044c \u043a\u0430\u043b\u043e\u0440\u0438\u0438 \u0431\u0435\u0441\u043f\u043b\u0430\u0442\u043d\u043e, \u0438 \u0437\u043d\u0430\u0442\u044c, \u0432 \u043a\u0430\u043a\u043e\u0439 \u043c\u043e\u043c\u0435\u043d\u0442 \u0438\u043c \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442\u0441\u044f \u043f\u043e\u0434\u043f\u0438\u0441\u043a\u0430. \u041d\u043e \u0422\u0420\u0418 \u0441\u0442\u0440\u043e\u043a\u0438, \u043a\u043e\u0433\u0434\u0430 \u043c\u043e\u0436\u043d\u043e \u043d\u0430\u043f\u0438\u0441\u0430\u0442\u044c \u043e\u0434\u043d\u0443? \u0414\u043b\u044f \u043b\u044e\u0431\u043e\u0433\u043e Ruby \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430 \u044d\u0442\u043e \u0437\u0432\u0443\u0447\u0438\u0442 \u043a\u0430\u043a \u0432\u044b\u0437\u043e\u0432. \u041f\u043e\u044d\u0442\u043e\u043c\u0443, \u0444\u0438\u043d\u0430\u043b\u044c\u043d\u044b\u0439 \u0444\u0438\u043a\u0441, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043f\u043e\u0448\u0435\u043b \u0432 \u043f\u0440\u043e\u0434 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0442\u0430\u043a:mealup\/app\/api\/v1\/api.rb:rescue_from SubscriptionRequiredError, with: -&gt;(e) { render_error(e) }\u0412\u044b\u0432\u043e\u0434\u044b1. \u0412 Grape rescue_from \u0441 \u0441\u0438\u043c\u0432\u043e\u043b\u043e\u043c (with: :render_error) \u043f\u0440\u0435\u0432\u0440\u0430\u0449\u0430\u0435\u0442 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u0432 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440 Method, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u0436\u0451\u0441\u0442\u043a\u043e \u043f\u0440\u0438\u0432\u044f\u0437\u0430\u043d \u043a \u043e\u0431\u044a\u0435\u043a\u0442\u0443 \u0438\u0437 middleware-\u0446\u0435\u043f\u043e\u0447\u043a\u0438 \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432\u043d\u0435 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442\u0430 Grape::Endpoint, \u0438\u0437-\u0437\u0430 \u0447\u0435\u0433\u043e \u0442\u0435\u0440\u044f\u0435\u0442 \u0434\u043e\u0441\u0442\u0443\u043f \u043a request.2. rescue_from \u0441 \u0431\u043b\u043e\u043a\u043e\u043c \u0438\u043b\u0438 \u043b\u044f\u043c\u0431\u0434\u043e\u0439 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442 \u043a\u043e\u043d\u0442\u0435\u043a\u0441\u0442 Grape::Endpoint \u0431\u043b\u0430\u0433\u043e\u0434\u0430\u0440\u044f \u0433\u0438\u0431\u043a\u043e\u0441\u0442\u0438 Proc.3. \u0415\u0441\u043b\u0438 \u0432\u0430\u0448 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a \u043e\u0448\u0438\u0431\u043a\u0438 \u043e\u0431\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u043a request, params, current_user \u0438\u043b\u0438 \u0434\u0440\u0443\u0433\u0438\u043c \u043c\u0435\u0442\u043e\u0434\u0430\u043c Grape::Endpoint \u2014 \u0432\u0441\u0435\u0433\u0434\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0439\u0442\u0435 \u043b\u044f\u043c\u0431\u0434\u0443 \u0438\u043b\u0438 \u0431\u043b\u043e\u043a.4. \u041a\u0440\u0430\u0441\u0438\u0432\u044b\u0439 \u0441\u0438\u043d\u0442\u0430\u043a\u0441\u0438\u0441 \u043d\u0435 \u0432\u0441\u0435\u0433\u0434\u0430 \u043f\u0440\u0430\u0432\u0438\u043b\u044c\u043d\u044b\u0439. \u0418\u043d\u043e\u0433\u0434\u0430 \u0437\u0430 \u043a\u0440\u0430\u0441\u043e\u0442\u043e\u0439 \u0441\u043a\u0440\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0431\u043e\u043b\u044c \u043c\u043d\u043e\u0433\u043e\u0447\u0430\u0441\u043e\u0432\u043e\u0433\u043e \u0434\u0435\u0431\u0430\u0433\u0430. (\u041d\u043e Ruby &#8212; \u0432\u0441\u0435 \u0440\u0430\u0432\u043d\u043e \u043a\u043b\u0430\u0441\u0441\u043d\u044b\u0439).\u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 https:\/\/habr.com\/ru\/articles\/1030354\/<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-478192","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/478192","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=478192"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/478192\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=478192"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=478192"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=478192"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}