Задать вопрос

Как передать параметры в контроллер для перехода redirect_to по условию?

Добрый день!

Я хотел бы наладить работу кнопки Submit на view в зависимости от внешних условий. Другими словами: если view не передаются дополнительные параметры, то Submit выбрасывает на список объектов (index.html.erb). Если же во view передаются параметры, то Submit в этом случае открывает объект, номер которого передан в этих самых параметрах.

Как я понимаю, это можно организовать через правильное написание условия в событии контроллера. Но, к сожалению, пока что не хватает знаний правильно всё организовать.

Есть следующая схема взаимосвязей (выписка из routes.rb):
Rails.application.routes.draw do

  resources :journals do
    resources :publications do
      resources :articles do
        resources :paternities
      end
    end
  end
  
  resources :authors
  ...
end


В данной схеме ресурсы articles и authors связаны друг с другом через paternities по схеме "многие-ко-многим" (у автора может быть много статей, у статьи может быть много авторов):

class Article < ActiveRecord::Base
  has_many :paternities
  has_many :authors, :through => :paternities
  belongs_to :publication
end 

class Author < ActiveRecord::Base
  has_many :paternities
  has_many :articles, :through => :paternities
end

class Paternity < ActiveRecord::Base
  belongs_to :author
  belongs_to :article
end


Для статей (articles) в show.html.erb есть возможность добавить автора к списку авторов статьи:

# app/views/authors/show.html.erb
# оформление убрано для читабельности кода

<%= @article.title %>

Авторы: <%= render @article.paternities %>

<%= link_to "Добавить автора", 
new_journal_publication_article_paternity_path(@journal, @publication, @article) %>

<%= link_to 'Вернуться к списку статей', 
journal_publication_articles_path(@journal, @publication) %>

<%= link_to 'Удалить статью из выпуска', 
journal_publication_articles_path(@journal, @publication), 
method: :delete, 
data: { confirm: 'Подтвердите удаление данной статьи из публикации сборника'} %>


Выбор нового автора происходит из списка авторов, которых ранее добавили. При этом если автора нет в списке, то его можно добавить при помощи ссылки "Нет автора в списке" - ссылки, которая передаёт в качестве параметров ID объектов для корректного возврата к статье после добавления автора:

# /app/views/paternities/new.html.erb
# оформление убрано для читабельности кода

<%= form_for [@journal, @publication, @article, @paternity], 
params:{url: journal_publication_article_path(@journal, @publication, @article)} 
do |f| %>
   
<%= 'Добавить автора к статье '+@article.title %>
 
<%= f.select(:author_id, Author.all.order('authors.surname').collect{|i| [ i.name_full, i.id ] }, 
{include_blank: true}) %> 

<%= link_to "Нет автора в списке", 
new_author_path(:journal_id => @journal.id, :publication_id => @publication.id, :article_id => @article.id) %>
  
<%= f.submit "Добавить автора к статье" %>
<%= link_to 'Отмена', 
journal_publication_article_path(@journal, @publication, @article), %>
 
<% end %>


После этого открывается окно добавления нового автора. Кнопка "Отмена" отрабатывает корректно - открывается нужная страница:

# /app/views/authors/new.html.erb
# оформление убрано для читабельности кода

<%= form_for @author do |f| %>
<%= 'Добавление автора' %>
  
# поля для заполнения пользователем убраны для улучшения читабельности кода

<%= f.submit "Добавить автора" %>
<% if params[:article_id] != nil %>
<%= link_to 'Отмена', 
journal_publication_article_path(Journal.find(params[:journal_id]), Publication.find(params[:publication_id]), Article.find(params[:article_id])) %>
<% else %>
<%= link_to 'Отмена', authors_path %>
<% end %>  
  
<% end %>


А при нажатии на Submit появляется ошибка в authors_controller.rb "Couldn't find Journal with 'id'=" на строке @journal = Journal.find(params[:journal_id])
class AuthorsController < ApplicationController

 ...
  
  def new
    @author = Author.new
  end
  
  def create
# здесь ошибка
    @journal = Journal.find(params[:journal_id])
    @publication = @journal.publications.find(params[:publication_id])
    @article = @publication.articles.find(params[:article_id]) 
    
    @author = Author.create(author_params)
 
    if @author.save
# для тестирования условие было закомментировано
#      if @article = nil
#        redirect_to @author
#      else  
        redirect_to new_journal_publication_article_paternity_path(@journal, @publication, @article)
#      end  
    else
      render 'new'
    end
  end
  
...
  
private  
  def author_params
    params.require(:author).permit(:surname, :mainname, :middlename, :email, :moretext)
  end   
 
end


Как я понял, параметр article_id не передался в контроллер. Но почему?
  • Вопрос задан
  • 1292 просмотра
Подписаться 2 Оценить Комментировать
Решения вопроса 1
@antooninc Автор вопроса
Разобрался. Оказалось, недостаточно передать параметры в view добавления нового автора. Необходимо было эти параметры пробросить дальше, так как при submit они автоматом не пробрасывались.

Решением оказалось добавление трёх hidden_field в /app/views/authors/new.html.erb в том случае, если в view были переданы параметры:
# /app/views/authors/new.html.erb
<%= form_for @author do |f| %>
<%= 'Добавление автора' %>
  
# поля для заполнения пользователем убраны для улучшения читабельности кода

  <% if params[:journal_id] != nil %>
    <%= hidden_field_tag(:journal_id, params[:journal_id]) %>
    <%= hidden_field_tag(:publication_id, params[:publication_id]) %>
    <%= hidden_field_tag(:article_id, params[:article_id]) %>
  <% end %>
...


Код в authors_controller.rb потребовал лишь косметических изменений:

class AuthorsController < ApplicationController
# менялся только код для create
  ...
  def create
    @author = Author.create(author_params)
 
    if params[:journal_id] != nil
      @journal = Journal.find(params[:journal_id])
      @publication = @journal.publications.find(params[:publication_id])
      @article = @publication.articles.find(params[:article_id]) 
    end  

    if @author.save
      if params[:journal_id] != nil
        redirect_to new_journal_publication_article_paternity_path(@journal, @publication, @article, :author_id => @author.id)
      else  
        redirect_to authors_path
      end  
    else
      render 'new'
    end
  end
  
...
  
end


После этого всё заработало как часы: при добавлении пользователя через ссылку "Нет автора в списке" пользователю показывается окно добавления нового автора. После нажатия на Submit пользователь возвращается назад к выпадающему списку авторов. А чтобы ему не искать свежедобавленного автора, в список добавлено "selected: params[:author_id]", плюс в форму передаётся author_id. Ну а если автор добавлялся из окна со списком авторов, то после нажатия на Submit пользователь возвращался назад к списку.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
malworm
@malworm
Антон Исаев я уже задавал похожий вопрос, связаный с использованием:has_many в ActiveRecord. Посмотрите ответ и комментарии, возможно, найдете решение
Как использовать has_many ActiveRecord?
Ответ написан
@evgeniy_trebin
Ruby on Rails developer
Как я вижу из роутов resources :authors не вложены в resources :journals, поэтому никакого journal_id там и не должно быть, только если не передавать его отдельным полем в форме
Ответ написан
@Coffin
Говорят, что > 3 вложений делать плохо.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы