A
A
Anton Isaev2016-02-06 23:17:46
Ruby on Rails
Anton Isaev, 2016-02-06 23:17:46

How to pass parameters to the controller for redirect_to transition by condition?

Good afternoon!
I would like to make the Submit button on the view work depending on external conditions. In other words: if no additional parameters are passed to the view, then Submit throws on the list of objects (index.html.erb). If parameters are passed to the view, then Submit in this case opens the object whose number is passed in these same parameters.
As I understand it, this can be arranged through the correct writing of the condition in the controller event. But, unfortunately, so far there is not enough knowledge to organize everything correctly.
There is the following relationship diagram (extract from routes.rb):

Rails.application.routes.draw do

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

In this scheme, the articles and authors resources are linked to each other through paternities in a many-to-many fashion (an author can have many articles, an article can have many authors):
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

For articles (articles) in show.html.erb it is possible to add the author to the list of article authors:
# 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: 'Подтвердите удаление данной статьи из публикации сборника'} %>

The choice of a new author comes from the list of authors that were previously added. Moreover, if the author is not in the list, then it can be added using the "No author in the list" link - a link that passes object IDs as parameters for correctly returning to the article after adding the author:
# /app/views/paternities/new.html.erb
# оформление убрано для читабельности кода

<%= form_for [@journal, @publication, @article, @paternity], 
params:{url: journal_publication_article_path(@journal, @publication, @article)} 
do |f| %>
   
<%= 'Добавить автора к статье '[email protected] %>
 
<%= 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 %>

After that, the window for adding a new author opens. The "Cancel" button works correctly - the desired page opens:
# /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 %>

And when you click Submit, you get an error in authors_controller.rb " Couldn't find Journal with 'id'= " on the line @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

As I understand it, the article_id parameter was not passed to the controller. But why?

Answer the question

In order to leave comments, you need to log in

4 answer(s)
A
Anton Isaev, 2016-02-07
@antooninc

Understood. It turned out that it was not enough to pass parameters to the view of adding a new author. It was necessary to forward these parameters further, since they were not automatically forwarded on submit.
The solution was to add three hidden_fields to /app/views/authors/new.html.erb if parameters were passed to the 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 %>
...

The code in authors_controller.rb required only cosmetic changes:
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

After that, everything worked like clockwork: when adding a user via the "No author in the list" link, the user is shown a window for adding a new author. After clicking Submit, the user is taken back to the authors drop-down list. And in order for it not to look for a freshly added author, "selected: params[:author_id]" is added to the list, plus author_id is passed to the form. Well, if the author was added from the window with the list of authors, then after clicking on Submit, the user returned back to the list.

M
mlwrm, 2016-02-06
@malworm

Anton Isaev I already asked a similar question related to the use :has_manyin ActiveRecord. Look at the answer and comments, maybe you will find a solution
How to use has_many ActiveRecord?

E
Evgeniy Trebin, 2016-02-07
@evgeniy_trebin

As I can see from the routes, resources :authors is not nested in resources :journals, so there should not be any journal_id there, unless you pass it as a separate field in the form

C
Coffin, 2016-02-09
@Coffin

They say that > ​​3 attachments are bad.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question