Rails 4 - Pundit - ограниченная политика для индекса

Я пытаюсь научиться использовать Pundit с моим приложением Rails 4.

У меня есть следующие модели:

class User < ActiveRecord::Base
  has_one :profile
  has_many :eois
end

class Profile < ActiveRecord::Base
  belongs_to :user
  has_many :projects, dependent: :destroy
end

class Project < ActiveRecord::Base
  belongs_to :profile
  has_many :eois
end

class Eoi < ActiveRecord::Base
  belongs_to :project
  belongs_to :user
end

У меня есть областьEoiPolicy с:

class EoiPolicy < ApplicationPolicy

  class Scope
    attr_reader :user, :scope

    def initialize(user, scope)
      @user  = user
      @scope = scope
    end

    def resolve
      if user.profile.project.id == @eoi.project_id?
        scope.where(project_id: @user.profile.project.id)
      elsif user.id == eoi.user_id?
        scope.where(user_id: user.id)
      else
        nil
      end
    end
  end

  def index?
    user.profile.project.id == @eoi.project_id? or user.id == eoi.user_id?
  end

  def new?
    true
  end

  def show?
    user.profile.project.id == @eoi.project_id? or user.id == eoi.user_id?
  end

  def edit?
    user.id == eoi.user.id?
  end

  def create?
    true 
  end

  def update?
    user.id == eoi.user.id?
  end

  def destroy?
    user.id == eoi.user.id?
  end    
end

В моемEoisControllerЯ попытался использовать область с:

def index
  # @eois = @project.eois
  @eois = policy_scope(Eoi)
  # @eois = Eois.find_by_project_id(params[:project_id])
end

Тогда по моемуview/eois/indexЯ попытался отобразить индекс с помощью:

<% policy_scope(@user.eois).each do |group| %>

Я не могу заставить это работать. Сообщение об ошибке выделяет эту строку моего метода области действия в политике:

if user.profile.project.id == @eoi.project_id?

Для меня это выглядит правильно, хотя я все еще пытаюсь понять это. Может ли кто-нибудь увидеть, что должно произойти, чтобы заставить эту работу работать, чтобы, если пользователь является пользователем, чей профиль владеет соответствующим проектом, все eois, относящиеся к этому проекту, видны.

Иначе, если пользователь является пользователем, создавшим Eoi, то все созданные Eois будут видимы?

Сообщение об ошибке говорит:

undefined method `project' for #<Profile:0x007fa03f3faf48>
Did you mean?  projects
               projects=

Мне интересно, если это потому, что индекс будет иметь много записей, он должен показать что-то другое в политике, чтобы распознать множественность?

Я также попытался заменить эту строку:

if  @eoi.project_id == @user.profile.project.id?

хотя это тоже неправильно и дает

undefined method `project_id' for nil:NilClass
Did you mean?  object_id

Я также попытался сделать прицел:

 def resolve
      # cant figure what is wrong with this
      if  eoi.project_id == user.profile.project.id?
        scope.where(project_id: @user.profile.project.id)
      else
        nil
      end
    end

но это тоже неправильно и выдает эту ошибку:

  undefined local variable or method `eoi' for #<EoiPolicy::Scope:0x007ffb505784f8>

Я также попробовал:

    def resolve
      # cant figure what is wrong with this

      if  @eoi.project_id == user.profile.project.id? or Eoi.project_id == user.profile.project.id?
        scope.where(project_id: @user.profile.project.id)
      elsif user.id == eoi.user_id?
        scope.where(user_id: user.id)
      else
        nil
      end
    end
  end



def index?
    user.profile.project.id == Eoi.project_id? or user.id == Eoi.user_id?
  end

но эта попытка дает это сообщение об ошибке:

undefined method `project_id' for nil:NilClass
Did you mean?  object_id

ТЕКУЩАЯ МЫСЛЬ

Я думаю, что мне нужно передать больше, чем пользователь и область видимости для метода видимости. Если я также могу передать проект, то я могу сделать область действия доступной для проекта, к которому относится ВЗ.

Если бы я мог работать так, то, возможно, я мог бы заставить метод области работать для представления индекса на контроллере:

class Scope
  attr_reader :user, :scope

  def initialize(user, scope, project)
    @user  = user
    @scope = scope
    @project = project
  end
end

затем в контроллере:

 def index
   # @eois = @project.eois

   @eois = policy_scope(Eoi, @project)
   # authorize @eois
   # @eois = Eois.find_by_project_id(params[:project_id])
 end

Это не работает, когда я пытаюсь получить сообщение об ошибке, утверждая, что политика

wrong number of arguments (given 2, expected 1)

Пожалуйста помоги!

СЛЕДУЮЩАЯ ПОПЫТКА

Моя следующая попытка состоит в том, чтобы попытаться принять предложения из [этой] проблемы Pundit и реализовать эту идею о том, как получить правильную область для конкретного пользователя.

В моей политике Eoi я изменил метод разрешения на:

class Scope
    attr_reader :user, :scope

    def initialize(user, scope) #project
      @user  = user
      @scope = scope
      # @project = project

    end

    def resolve
      # if  Eoi.project_id == user.profile.project.id? or Eoi.project_id == user.profile.project.id?
      if user.id == eoi.projects.profile.user.map(&:id)
        scope.joins(eois: :projects).where(project_id: user.profile.projects.map(&:id)).empty?
      # if scope.eoi.project_id == user.profile.projects.map(&:id)  
        # scope.where(project_id: user.profile.projects.map(&:id)).empty? 
      #   scope.where(project_id: user.profile.project.id)
      # elsif user.id == eoi.user_id?
      #   scope.where(user_id: user.id)
      else
      #   nil
       end
    end
  end

Затем в моем действии индекса контроллера eoi я попытался это:

def index
    # @eois = @project.eois

    # @eois = policy_scope(Eoi, @project)
    policy_scope(Eoi).where(project_id: params[:project_id])
    # authorize @eois
    # @eois = Eois.find_by_project_id(params[:project_id])
  end

Это тоже не работает. Сообщение об ошибке для этой попытки говорит:

undefined local variable or method `eoi' for #<EoiPolicy::Scope:0x007f98677c9cf8>

У меня нет идей для того, чтобы попробовать. Может кто-нибудь увидеть способ дать прицел правильные входы для настройки этого?

НАБЛЮДЕНИЯ Я заметил, что многие репозитории на github, которые используют Pundit с областями действия, также включают такой метод:

def scope
  Pundit.policy_scope!(user, record.class)
end

Этот метод является дополнением к классу Scope и не показан в документации по драгоценным камням Pundit. Если это необходимо включить, что это делает?1

REWRITE

Сейчас я просмотрел более 200 репозиториев на github, чтобы понять, как я должен написать политику для достижения моих целей. У меня нет идей, как использовать Pundit по назначению.

Я полностью изменил мои настройки, чтобы попытаться обойти биты, которые я не могу понять. Теперь у меня есть:

Eois Controller

class EoisController < ApplicationController

  def index
    @eois = Eoi.by_user_id(current_user.id)
  end
end

Проекты :: Eois controller

module Projects
  class EoisController < ApplicationController
    before_action :get_project
    before_action :set_eoi, only: [:edit, :update, :destroy]
    # after_action :verify_authorized

    def index
      @eois = Project.by_user_id(current_user.id).find_by(id: params[:project_id]).try(:eois) || []
    end

 def show
      @eoi = Eoi.find(params[:id])
      authorize @eoi
    end

def set_eoi
        @eoi = EoiPolicy::Scope.new(current_user, params[:project_id]).resolve.find(params[:id])
      end

      def get_project
        @project = Project.find(params[:project_id])
      end

Политика Eoi (чтобы решить, когда показывать все Eois, сделанные пользователем)

class EoiPolicy < ApplicationPolicy

  class Scope
    attr_reader :user, :scope

    def initialize(user, scope)
      @user  = user
      @scope = scope
    end

    def resolve
      if scope.present?
          Eoi.by_user_id(user.id)
        # end
      else
        []
      end
    end

  end

  def index?
    user.profile.project.id == Eoi.project_id? or user.id == Eoi.user_id?
  end

  def new?
    true
  end

  def show?
    record.user_id == user.id || user.profile.project_id == record.project_id
    # user.profile.project.id == @eoi.project_id? or user.id == eoi.user_id?
  end

  def edit?
    user.id == eoi.user.id?
  end

  def create?
    true
  end

  def update?
    user.id == eoi.user.id?
  end

  def destroy?
    user.id == eoi.user.id?
  end


end

Маршруты

resources :eois

resources :projects do
    member do
    resources :eois, controller: 'projects/eois
  end

Когда я хочу показать EoI, представленные в отношении проекта, я использую Политику Eoi для проектов, а когда я хочу показать Eois, созданные пользователем, я использую Политику Eoi - никаких областей действия.

Я хотел бы понять это, чтобы я мог использовать этот драгоценный камень так, как он предназначен. Совет будет принята с благодарностью. Я уверен, что эта попытка - не то, для чего предназначен Pundit - но я не могу понять, как использовать этот драгоценный камень, как показано в документации.

Я не могу использовать policy_scope, потому что мне нужно передать параметр project_id в действие index для действия index eoi controller проектов.

ПАРЕОНОС ПРЕДЛОЖЕНИЕ

Моя попытка реализовать предложение PareeOhNos изложена ниже. Я не уверен, что правильно понимаю, потому что eois всегда будет иметь идентификатор проекта и идентификатор пользователя, но, возможно, я не понимаю, что делает метод load_parent.

В моем контроллере Eois у меня есть:

class EoisController < ApplicationController
  before_action :load_parent
  before_action :load_eoi, only: [:show, :edit, :update, :destroy]



  def index
    authorize @parent
    @eois = EoiPolicy::Scope.new(current_user, @parent).resolve
  end



  def show

  end

  # GET /eois/new
  def new
    @project = Project.find(params[:project_id])
    @eoi = @project.eois.build
    @contribute = params[:contribute] || false
    @participate = params[:participate] || false
    @partner = params[:partner] || false
    @grant = params[:grant] || false
    @invest = params[:invest] || false
  end

  # GET /eois/1/edit
  def edit
  end

  # POST /eois
  # POST /eois.json
  def create
    @eoi = Project.find(params[:project_id]).eois.build(eoi_params)
    @eoi.user_id = @current_user.id

    respond_to do |format|
      if @eoi.save
        format.html { redirect_to Project.find(params[:project_id]), notice: 'Eoi was successfully created.' }
        format.json { render :show, status: :created, location: @project }
      else
        format.html { render :new }
        format.json { render json: @eoi.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /eois/1
  # PATCH/PUT /eois/1.json
  def update
    respond_to do |format|
      if @eoi.update(eoi_params)
        format.html { redirect_to @project, notice: 'Eoi was successfully updated.' }
        format.json { render :show, status: :ok, location: @eoi }
      else
        format.html { render :edit }
        format.json { render json: @eoi.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /eois/1
  # DELETE /eois/1.json
  def destroy
    @eoi.destroy
    respond_to do |format|
      format.html { redirect_to @project, notice: 'Eoi was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

    def load_parent
      # @parent = (params[:project_id] ? Project.find(params[:project_id] : current_user)
      @parent =  params[:project_id] ? Project.find(params[:project_id]) : current_user
    end

    def load_eoi
      @eoi = Eoi.find(params[:id])
      authorize @eoi
    end

В моей политике Eoi у меня есть:

class EoiPolicy < ApplicationPolicy
class Scope
    attr_reader :user, :scope

    def initialize(user, scope)
      @user  = user
      @scope = scope
    end

    def resolve
      if scope.is_a?(User)
        Eoi.where(user_id: scope.id)
      elsif scope.is_a?(Project)
        Eoi.where(project_id: scope.id)
      else
        []
      end
    end

  end

  def index?
    record.is_a?(User) || user.profile.project.id == record.project_id
  end

  def new?
    true
  end

  def show?
    record.user_id == user.id || user.profile.project_id == record.project_id
  end

  def edit?
    user.id == eoi.user.id?
  end

  def create?
    true
  end

  def update?
    user.id == eoi.user.id?
  end

  def destroy?
    user.id == eoi.user.id?
  end


end

В моем route.rb у меня есть:

resources :projects do
    member do
  resources :eois, shallow: true

resources :eois, only: [:index]

В моем eois / index у меня есть:

    <% @eois.sort_by(&:created_at).in_groups_of(2) do |group| %>
        <% group.compact.each do |eoi| %>
            <h4><%= link_to eoi.user.full_name %></h4>
            <%= link_to 'VIEW DETAILS', eoi_path(eoi), :class=>"portfolio-item-view" %>
<% end %>  
<% end %>  

В моем фильме / шоу я имею:

"test"

Когда я все это пробую, страница eois / index загружается. Когда я пытаюсь показать определенную страницу EOI, я получаю сообщение об ошибке:

wrong number of arguments (given 2, expected 0)

сообщение об ошибке указывает на авторизацию @eoi строки контроллера:

def load_eoi
      @eoi = Eoi.find(params[:id])
      authorize @eoi
    end

Та же ошибка возникает, если я добавлю authorize @eoi в действие show вместо метода load eoi.

ПОЛИТИКА ПРИМЕНЕНИЯ ИМЕЕТ

class ApplicationPolicy
  attr_reader :user,  :scope

  class Scope
    def initialize(user, scope)
      #byebug        
      @user = user
      # record = record
      @scope = scope
    end

    def resolve
      scope
    end
  end

  def index?
    false
  end

  def show?
    scope.where(:id => record.id).exists?
  end

  def create?
    false
  end

  def new?
    create?
  end

  def update?
    false
  end

  def edit?
    update?
  end

  def destroy?
    false
  end

  def scope
    Pundit.policy_scope!(user, record.class)
  end

СЛЕДУЮЩАЯ ПОПЫТКА

Принимая предложение PaReeOhNos (скопировано выше), я попытался немного его адаптировать, чтобы он лучше подходил моим сценариям использования.

Теперь у меня есть:

Eoi контроллер

class EoisController < ApplicationController
  # before_action :get_project
  # before_action :set_eoi, only: [:show, :edit, :update, :destroy]
  before_action :load_parent
  before_action :load_eoi, only: [:show, :edit, :update, :destroy]


  # GET /eois
  # GET /eois.json
  # def index
  #   @eois = @project.eois
  #   # @eois = Eois.find_by_project_id(params[:project_id])
  # end

  def index
    # authorize @parent
    @eois = policy_scope(Eoi.where(project_id: params[:project_id]))
    # @eois = EoiPolicy::Scope.new(current_user, @parent).resolve
  end


  # GET /eois/1
  # GET /eois/1.json
  def show

  end

  # GET /eois/new
  def new
    @project = Project.find(params[:project_id])
    @eoi = @project.eois.build
    @contribute = params[:contribute] || false
    @participate = params[:participate] || false
    @partner = params[:partner] || false
    @grant = params[:grant] || false
    @invest = params[:invest] || false
  end

  # GET /eois/1/edit
  def edit
  end

  # POST /eois
  # POST /eois.json
  def create
    @eoi = Project.find(params[:project_id]).eois.build(eoi_params)
    @eoi.user_id = @current_user.id

    respond_to do |format|
      if @eoi.save
        format.html { redirect_to Project.find(params[:project_id]), notice: 'Eoi was successfully created.' }
        format.json { render :show, status: :created, location: @project }
      else
        format.html { render :new }
        format.json { render json: @eoi.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /eois/1
  # PATCH/PUT /eois/1.json
  def update
    respond_to do |format|
      if @eoi.update(eoi_params)
        format.html { redirect_to @project, notice: 'Eoi was successfully updated.' }
        format.json { render :show, status: :ok, location: @eoi }
      else
        format.html { render :edit }
        format.json { render json: @eoi.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /eois/1
  # DELETE /eois/1.json
  def destroy
    @eoi.destroy
    respond_to do |format|
      format.html { redirect_to @project, notice: 'Eoi was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

    def load_parent
      # @parent = (params[:project_id] ? Project.find(params[:project_id] : current_user)
      @parent = params[:project_id] ? Project.find(params[:project_id]) : current_user
    end

    def load_eoi
      @eoi = Eoi.find(params[:id])
      # authorize @eoi
    end

Политика Eoi

class EoiPolicy < ApplicationPolicy

  class Scope
    attr_reader :user, :scope

    def initialize(user, scope)
      @user  = user
      @scope = scope
    end

    def resolve
      # since we send the scoped eois from controller, we can pick
      # any eoi and get its project id

      # check if the current user is the owner of the project
    #   if (user.profile.projects.map(&:id).include?(project_id))
    #     # user is the owner of the project, get all the eois 
    #     scope.all 
    #   end
    #   #not the owner , then get only the eois created by the user
    #   scope.where(user_id: user.id)
    # end 
      if scope.is_a?(User)
        Eoi.where(user_id: scope.id)
      elsif scope.is_a?(Project) && (user.profile.projects.map(&:id).include?(project_id))
        project_id = scope.first.project_id 
        Eoi.where(project_id: scope.id)
      else
        Eoi.none
      end
    end

  end

  def index?
    record.is_a?(User) || user.profile.project.id == record.project_id
  end

  def new?
    true
  end

  def show?
    record.user_id == user.id || user.profile.project_id == record.project_id
  end

  def edit?
    user.id == eoi.user.id?
  end

  def create?
    true
  end

  def update?
    user.id == eoi.user.id?
  end

  def destroy?
    user.id == eoi.user.id?
  end


end

Маршруты

resources :eois#, only: [:index]
  concern :eoiable do
    resources :eois
  end

resources :projects do
    concerns :eoiable
  end

Индекс

   <% @eois.sort_by(&:created_at).in_groups_of(2) do |group| %>
     <% group.compact.each do |eoi| %>
     <h4><%= link_to eoi.user.full_name %></h4>
     <%= link_to 'VIEW DETAILS', project_eoi_path(eoi.project, eoi), :class=>"portfolio-item-view" %>
                            <% end %>  
                        <% end %>   

Посмотреть

'test'

Это не работает, потому что, когда я перехожу к проекту и затем пытаюсь отобразить индекс eois с соответствующим идентификатором проекта, я получаю пустую страницу индекса, когда у меня есть 4 записи в моей базе данных, которые должны быть отображены.

ПРЕДЛОЖЕНИЕ ЛЕЙТО

Принимая предложение Лейто, я также попробовал это:

Eoi Controller

class EoisController < ApplicationController
  before_action :get_project
  before_action :set_eoi, only: [:show, :edit, :update, :destroy]
  # before_action :load_parent
  # before_action :load_eoi, only: [:show, :edit, :update, :destroy]


  # GET /eois
  # GET /eois.json
  # def index
  #   @eois = @project.eois
  #   # @eois = Eois.find_by_project_id(params[:project_id])
  # end

  def index
    # authorize @eois
    # authorize @parent
    # policy_scope(@project.eois)
    @eois = policy_scope(Eoi.where(project_id: params[:project_id]))
    # @eois = EoiPolicy::Scope.new(current_user, @parent).resolve
  end


  # GET /eois/1
  # GET /eois/1.json
  def show

  end

  # GET /eois/new
  def new
    @project = Project.find(params[:project_id])
    @eoi = @project.eois.build
    @contribute = params[:contribute] || false
    @participate = params[:participate] || false
    @partner = params[:partner] || false
    @grant = params[:grant] || false
    @invest = params[:invest] || false
  end

  # GET /eois/1/edit
  def edit
  end

  # POST /eois
  # POST /eois.json
  def create
    @eoi = Project.find(params[:project_id]).eois.build(eoi_params)
    @eoi.user_id = @current_user.id

    respond_to do |format|
      if @eoi.save
        format.html { redirect_to Project.find(params[:project_id]), notice: 'Eoi was successfully created.' }
        format.json { render :show, status: :created, location: @project }
      else
        format.html { render :new }
        format.json { render json: @eoi.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /eois/1
  # PATCH/PUT /eois/1.json
  def update
    respond_to do |format|
      if @eoi.update(eoi_params)
        format.html { redirect_to @project, notice: 'Eoi was successfully updated.' }
        format.json { render :show, status: :ok, location: @eoi }
      else
        format.html { render :edit }
        format.json { render json: @eoi.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /eois/1
  # DELETE /eois/1.json
  def destroy
    @eoi.destroy
    respond_to do |format|
      format.html { redirect_to @project, notice: 'Eoi was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private

    # def load_parent
    #   # @parent = (params[:project_id] ? Project.find(params[:project_id] : current_user)
    #   @parent = params[:project_id] ? Project.find(params[:project_id]) : current_user
    # end

    # def load_eoi
    #   @eoi = Eoi.find(params[:id])
    #   # authorize @eoi
    # end
    # # Use callbacks to share common setup or constraints between actions.
    def set_eoi
      @eoi = Eoi.find(params[:id])
    end

    def get_project
      @project = Project.find(params[:project_id])
    end

Политика Eoi

def initialize(user, scope)
      @user  = user
      @scope = scope
    end

    def resolve

      if scope.joins(project: :profile).where profiles: { user_id: user }
        Eoi.where(project_id: scope.ids)
      elsif scope.joins(eoi: :user).where eois: { user_id: user }  
        Eoi.where(user_id: scope.ids)
      else
        Eoi.none
      end  
      # since we send the scoped eois from controller, we can pick
      # any eoi and get its project id

      # check if the current user is the owner of the project
    #   if (user.profile.projects.map(&:id).include?(project_id))
    #     # user is the owner of the project, get all the eois 
    #     scope.all 
    #   end
    #   #not the owner , then get only the eois created by the user
    #   scope.where(user_id: user.id)
    # end 
      # if scope.is_a?(User)
      #   Eoi.where(user_id: scope.id)
      # elsif scope.is_a?(Project) && (user.profile.projects.map(&:id).include?(project_id))
      #   project_id = scope.first.project_id 

      #   Eoi.where(project_id: scope.id)
      # else
      #   Eoi.none
      # end
    end

  end

  def index?
    true
    # record.is_a?(User) || user.profile.project.id == record.project_id
  end

  def new?
    true
  end

  def show?
    true
    # record.user_id == user.id || user.profile.project_id == record.project_id
  end

  def edit?
    user.id == eoi.user.id?
  end

  def create?
    true
  end

  def update?
    user.id == eoi.user.id?
  end

  def destroy?
    user.id == eoi.user.id?
  end


end

Маршруты и виды те же, что и при попытке выше

Проблема здесь заключается в методе get project в моем контроллере. Мне это нужно для сценария, в котором я пытаюсь показать все эти мысли по конкретному проекту. Мне не нужно, когда я пытаюсь показать все eois пользователя.

Когда я сохраняю все это и пытаюсь это сделать, эоиски в проекте отображаются правильно. Однако eois (не вложенный в проект), который должен показывать мне все мои (как пользователь) eois, показывает ошибку, которая говорит:

Couldn't find Project with 'id'=

Сообщение об ошибке выделяет «метод get_project».

ОБНОВЛЕННОЕ ПРЕДЛОЖЕНИЕ ЛЕЙТО

Принимая обновленное предложение Лейто, я изложил текущую попытку.

Прежде чем сделать это, я хочу уточнить, что все Eois будут иметь как идентификатор пользователя, так и идентификатор проекта. Я использую эту таблицу для пользователей, чтобы выразить интерес к проектам. Моя цель - чтобы пользователь, чей профиль владел проектом, мог видеть все eois, представленные в этом проекте. Затем я также хочу, чтобы пользователи видели все свои собственные eois, представленные (во всех проектах).

Политика Eoi

def resolve
  if scope.joins(project: :profile).where 'profiles.user_id = ? OR eois.user_id = ?', user.id, user.id
   Eoi.all
  else
    Eoi.none
  end  

Eoi контроллер

def index
    @eois = policy_scope(Eoi)
    @eois = @eois.where(project_id: params[:project_id]) if params[:project_id]
  end

В настоящее время это прекрасно работает при поиске eois, вложенных в проект (project / 26 / eois). Однако, когда я пытаюсь выполнить eois / index (не вложенный в проект), который я хочу вернуть всем eois пользователя, я получаю сообщение об ошибке:

Couldn't find Project with 'id'=

Это выделяет эту строку контроллера eoi:

def get_project
  @project = Project.find(params[:project_id])
end

Я не уверен, что теперь понимаю метод разрешения или идею отбраковки контроллера. Я не вижу, что не так с линией области видимости, чтобы увидеть, что можно изменить.

Ответы на вопрос(3)

Ваш ответ на вопрос