#ruby-on-rails
Вопрос:
У меня есть приложение Fantasy Soccer Rails, и я пытаюсь добавить функцию, которая заключается в том, чтобы каждый пользователь делал выбор проекта, по одному пользователю за раз, один за другим; как я могу это сделать? Пользователь создает строку, относящуюся к каждому выбранному игроку, чтобы сохранить его в своей личной команде. Вот часть кода, который, как я думаю, касается этой функции, но требуется больше, пожалуйста, скажите мне. Спасибо
пользователь.rb
class User lt; ApplicationRecord # Include default devise modules. Others available are: # :confirmable, :lockable, :timeoutable, :trackable and :omniauthable devise :database_authenticatable, :registerable, :recoverable, :rememberable, :validatable has_one :squad end
users_controller.rb
class UsersController lt; ApplicationController def update skip_authorization @user = current_user @user.update(user_params) redirect_to profile_path end def user_params params.require(:user).permit(:first_name, :last_name, :mobile, :drft_pass, :drft_shortlist) end has_one :squad end
line_item.rb
class LineItem lt; ApplicationRecord belongs_to :player belongs_to :squad end
line_items_controller.rb
class LineItemsController lt; ApplicationController before_action :set_line_item, only: [:destroy] before_action :set_player, only: [:create] def create #@player_id = @player #chosen_player = @player #@squad_id = @squad #current_squad = @current_squad if LineItem.where(squad_id: params[:squad_id]).where(player_id: params[:player_id]).count gt; 0 message = 'This player is already on your Squad' elsif LineItem.where(player_id: params[:player_id]).present? message = 'This player is already selected by other Coach' else @line_item = LineItem.new @player = Player.find(params[:player_id]) @squad = Squad.find(params[:squad_id]) @line_item.squad = @squad @line_item.player = @player @line_item.save message = 'Success. The player was added to your Squad' end redirect_to players_path flash[:notice] = message end def destroy @line_item.destroy redirect_to user_squad_path(current_user.id, :squad_id) end private def line_item_params params.require(:line_item).permit(:player_id, :squad_id) end def set_line_item @line_item = LineItem.find(params[:id]) end def set_player @player = Player.find(params[:player_id]) end end
player.rb
class Player lt; ApplicationRecord include PgSearch::Model pg_search_scope :search_by_full_name, against: [:name, :club, :pos] end
players_controller.rb
class PlayersController lt; ApplicationController #before_action :set_players, only: [:show, :edit, :update, :destroy] def index if params[:term] @players = Player.search_by_full_name(params[:term]).paginate(page: params[:page], per_page: 20) else @players = Player.paginate(page: params[:page], per_page: 20) end end def show @player = Player.find(params[:id]) end private def player_params params.require(:player).permit() end def set_player @player = Player.find(params[:id]) end end
squad.rb
class Squad lt; ApplicationRecord has_one_attached :photo belongs_to :user has_many :line_items, dependent: :destroy has_many :players, through: :line_items validates :name, presence: true end
squads_controller.rb
class SquadsController lt; ApplicationController before_action :authenticate_user! #before_action :set_squad def show end def new @user = User.find(params[:user_id]) @squad = Squad.new end def create @user = User.find(params[:user_id]) @squad = Squad.new(squad_params) @squad.user = @user if @squad.save redirect_to user_squad_path(current_user.id, @squad) flash[:notice] = 'Success. Your squad was created' else render "new" flash[:notice] = 'Squad not created; please try again' end end def edit @user = User.find(params[:user_id]) @squad = Squad.find(params[:squad_id]) end def update @user = User.find(params[:user_id]) @squad = Squad.find(params[:id]) @squad.update(squad_params) redirect_to user_squad_path(current_user.id, @squad) end def destroy @squad = Squad.find(params[:squad_id]) @squad.destroy redirect_to root_path end private def set_squad @squad = @current_squad end def squad_params params.require(:squad).permit(:name, :sigla, :photo) end end
Ответ №1:
Итак, здесь многое происходит — слишком многое, чтобы мы могли помочь в одном вопросе. Говоря «Это не работает, пожалуйста, исправьте это», вы не получите полезных ответов. Что именно не работает? Как это не работает? И в чем именно вам нужна помощь?
Однако несколько простых советов для начала. Во-первых, вы могли бы намного лучше использовать встроенные помощники Rails. Например, в вашем line_items_controller
, попробуйте что-то вроде этого:
def create line_item = LineItem.find_by(player_id: line_item_params[:player_id]) if line_item.present? message = if line_item.squad_id == current_user.squad_id 'This player is already on your Squad' else 'This player is already selected by other Coach' end else @line_item = LineItem.new @line_item.squad = current_user.squad @line_item.player = Player.find(line_item_params[:player_id]) message = if @line_item.save 'Success. The player was added to your Squad' else "Error - couldn't save your selection" end end flash[:notice] = message redirect_to players_path end
Обратите внимание, что при использовании current_user.squad будет возвращена связанная запись, а squad.line_items вернет связанные записи. Это означает, что (а) вам не нужно писать запросы и (б) вы всегда будете защищать себя от случайного предоставления пользователю доступа к записям, к которым у них не должно быть доступа (например, к командам других людей).
Я также изменил логику вашего if
блока, чтобы уменьшить количество запросов к базе данных. Во-первых, найдите строку, содержащую этого игрока (используя find_by
, а не where
потому, что, предположительно, должна быть только одна такая запись, потому что Игрок должен быть только в одной команде). Если есть какие-либо записи, проверьте, совпадает ли состав для этого элемента строки с составом текущего пользователя, и измените сообщение в зависимости от этого.
Затем назначьте игрока в команду пользователя, если они доступны, почти так же, как вы делали раньше. Вы не используете строгие параметры, даже если вы определили необходимый метод, например, в line_items_controller. Вы заметите, что я вставил эту ссылку в приведенный выше пример. Большое изменение в этом блоке заключается в том, что лучше избегать использования squad
параметра, потому что (предположительно) каждый пользователь может создавать элементы строк только для своего отряда! Так что я поменял это на current_user.squad
.
И обратите внимание, что вам нужно настроить флэш — сообщение перед перенаправлением-это фактически конец вашего метода.
Это дает вам один (!) из ваших методов, очищенных и, надеюсь, делающих то, что вы хотите. Но в целом, как я уже сказал, вам, вероятно, придется рассказать нам, в чем именно заключается ваша проблема.
Комментарии:
1. Спасибо за помощь… Я знал, что код не очень СУХОЙ, но он все еще находится на ранней стадии, я планирую провести некоторую очистку и наверняка воспользуюсь вашими идеями… Но все работает нормально, моя представленная проблема была больше связана с добавлением того, что следующая функция каждого пользователя делает выбор черновика, каждый раз по одному, но не знает, с чего начать
2. Речь идет не столько о сухости, сколько об эффективном использовании помощников Rails. И я думаю, что вам нужно гораздо яснее представлять свою реальную проблему — из вопроса следует, что код не работает, а не то, что вы хотите получить совет о том, как добавить новую функцию (и даже зная это, совсем не ясно, в чем ваша реальная проблема!).
3. ОК… Я переработаю вопрос и постараюсь немного прояснить, что мне нужно, спасибо… Как я уже сказал, все работает нормально, просто хочу добавить эту новую функцию
4. Звучит хорошо. Ключом будет: (1) то, что происходит сейчас; (2) что вы хотите изменить; и (3) какие ключевые биты кода задействованы. В идеале также то, что вы уже пробовали и что именно идет не так.