Связь Rails 4 ActiveRecord с вложенным полем формы

#ruby-on-rails-4 #rails-activerecord

#ruby-on-rails-4 #rails-activerecord

Вопрос:

Я прочитал половину всего, что смог достать, и, хотя есть разделы с очень четкими объяснениями того, что я пытаюсь сделать, я не могу найти актуальный полный учебник. У меня есть страницы и категории. Страницы имеют множество категорий, а категории — множество. Я также настроил 3-ю модель categories_pages и создал индексированную таблицу соединений с 2 столбцами в ней (category_id и page_id). Итак, мои модели в настоящее время:

 class Categorization < ActiveRecord::Base

belongs_to :category
belongs_to :page
end


class CategoriesPages < ActiveRecord::Base

belongs_to :category
belongs_to :page
end

class Page < ActiveRecord::Base

#categories
has_many :categories_pages
has_many :categories, :through => :categories_pages
end
  

Затем у меня есть форма, которая выглядит следующим образом (пожалуйста, не обращайте внимания на то, что в модели страницы выше отсутствует код скрепки .. я вырезал его из этого примера, но могу подтвердить загрузку файлов, как и должно быть).

     <%= form_for(@page) do |f| %>
  <% if @page.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@page.errors.count, "error") %> prohibited this page from being saved                          </h2>

      <ul>
      <% @page.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <form role="form">
    <div class="form-group">
      <%= f.label :title %><br>
      <%= f.text_field :title, :class => 'form-control' %>
    </div>
    <div class="form-group">
      <%= f.label :text %><br>
      <%= f.text_field :text, :class => 'form-control' %>
    </div>
    <div class="form-group">
      <%= form_for @page, :url => pages_path, :html => { :multipart => true } do |form| %>
        <%= form.file_field :image %>
      <% end %>
    </div>
    <div class="form-group">
      <%= f.fields_for :category do |cat| %>
        <%= cat.label :name, 'Category' %> </br>
        <%= cat.text_field :name %>
      <% end %>
    </div>
    <div class="form-group">
      <%= f.label :published %><br>
      <%= f.check_box :published, :class => 'checkbox' %>
    </div>
    <div class="form-group">
      <%= f.label :seo_keywords, 'SEO Keywords' %><br>
      <%= f.text_field :seo_keywords, :class => 'form-control' %>
    </div>
    <div class="form-group">
      <%= f.label :seo_description, 'SEO Description' %><br>
      <%= f.text_field :seo_description, :class => 'form-control' %>
    </div>
    <div class="action">
      <%= f.submit 'Save', :class => 'btn btn-default' %>
    </div>
  </form>

<% end %>
  

Мой вопрос в том, что мне вставить в контроллер / контроллеры (при условии, что приведенный выше код проверен). Я не нашел актуальной информации об этом. Railscasts устарел, и чем больше я читаю (я пытался решить это со вчерашнего дня), тем больше я ходил по кругу. На данный момент у меня есть рендеринг формы в режиме редактирования или создания, но кнопка сохранения полностью не отвечает. Я не уверен, что мой код контроллера правильный (только моя вторая неделя использования rails), поэтому я его не опубликовал. Любая помощь будет с благодарностью.

Редактировать 1:

Я забыл эту важную информацию. Форма отлично отображается без ошибок, однако кнопка отправки не отвечает (я нажимаю на нее, и ничего не происходит). Форма отлично сохраняется при удалении поля категории.

Правка 2: информация о журнале

 Started GET "/pages/8/edit" for 127.0.0.1 at 2014-06-23 03:27:33  0800
Processing by PagesController#edit as HTML
  Parameters: {"id"=>"8"}
  [1m[36mPage Load (1.3ms)[0m  [1mSELECT  `pages`.* FROM `pages`  WHERE `pages`.`id` = 8 LIMIT 1[0m
  Rendered pages/_form.html.erb (29.9ms)
  Rendered pages/edit.html.erb within layouts/application (31.7ms)
  [1m[35mUser Load (2.7ms)[0m  SELECT  `users`.* FROM `users`  WHERE `users`.`id` = 4 LIMIT 1
Completed 200 OK in 184ms (Views: 67.8ms | ActiveRecord: 88.1ms)


Started GET "/assets/categories.css?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/menu.css?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/adminpanel.css?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/posts.css?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/pages.css?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/sessions.css?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/scaffolds.css?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/users.css?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/bootstrap.min.css?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/jquery_ujs.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/jquery.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/categories.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/posts.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/application.css?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/sessions.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/menu.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/adminpanel.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/application.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/turbolinks.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/bootstrap.min.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/pages.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800


Started GET "/assets/users.js?body=1" for 127.0.0.1 at 2014-06-23 03:27:34  0800
  

Правка 3: pages_controller

 class PagesController < ApplicationController
  before_action :set_page, only: [:show, :edit, :update, :destroy]

  # GET /pages
  # GET /pages.json
  def index
      @pages = Page.all
  end

  # GET /pages/1
  # GET /pages/1.json
  def show
    @page = Page.new(page_params)
  end

  # GET /pages/new
  def new
    @category = Category.new
    @page = Page.new
  end

  # GET /pages/1/edit
  def edit

  end


  # POST /pages
  # POST /pages.json
  def create
    @page = Page.new(page_params)
    @category = @page.build_category(category_params)

    respond_to do |format|
      if @page.save
        format.html { redirect_to @page, notice: 'Page was successfully created.' }
        format.json { render :show, status: :created, location: @page }
      else
        format.html { render :new }
        format.json { render json: @page.errors, status: :unprocessable_entity }
      end
    end
  end


  # PATCH/PUT /pages/1
  # PATCH/PUT /pages/1.json
  def update
    @page = Page.new(page_params)
    @category = @page.category

    @category.assign_attributes(category_params)
    respond_to do |format|
      if @page.update_attributes(page_params)
        format.html { redirect_to @page, notice: 'Page was successfully updated.' }
        format.json { render :show, status: :ok, location: @page }
      else
        format.html { render :edit }
        format.json { render json: @page.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /pages/1
  # DELETE /pages/1.json
  def destroy
    @page.destroy
    respond_to do |format|
      format.html { redirect_to pages_url, notice: 'Page was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_page
      @page = Page.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def page_params
      params.require(:page).permit(:title, :text, :image, :published, :seo_keywords, :seo_description)
    end

    def category_params
      params.require(:category).permit(:name)
    end
end
  

Комментарии:

1. Вы получили какую-либо ошибку? Также, пожалуйста, укажите, в чем именно проблема.

2. Извините.. Я обновил вопрос. Проблема в том, что кнопка отправки формы полностью не отвечает.

3. Правильно ли сохраняются значения? Пожалуйста, опубликуйте информацию о журнале. А также эта строка <%= f.fields_for :category do |cat| %> должна быть <%= f.fields_for :categories do |cat| %> , если она has_many связана с категорией.

4. Хорошо исправлена проблема с категориями (она осталась с тех пор, как я вместо этого попробовал использовать отношение один к одному). Я вставил development.log, нажав «Редактировать» на странице, а затем попытался обновить и сохранить его. Как вы можете видеть, ничего не происходит, когда я нажимаю f.отправить

5. Выполнено. Я разместил только контроллер страниц, поскольку предполагаю, что это единственный контроллер, который имеет отношение к делу?

Ответ №1:

form_for Тег генерирует весь необходимый html для <form> тега, включая действие, метод и так далее. Взгляните на сгенерированный исходный код, чтобы понять, что делает «магия». Вы видите «ничего не происходит», потому что ваша кнопка отправки помещена в другой <form> блок (вне блока form_for), у которого нет action набора атрибутов. И — вы видите — нет action приводит к «нет действий».

Обновить:

Чтобы исправить поведение, присоединитесь к формам следующим образом:

 <%= form_for @page, html: { role: 'form' } do |f| %>
  <div id="error_explanation">
    <h2><%= pluralize(@page.errors.count, "error") %> prohibited this page from being saved </h2>
    <ul>
      <% @page.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
    </ul>
  </div>
  <div class="form-group">
    <%= f.label :title %><br>
    <%= f.text_field :title, :class => 'form-control' %>
  </div>
  <div class="form-group">
    <%= f.label :text %><br>
    <%= f.text_field :text, :class => 'form-control' %>
  </div>
  ...
  <div class="action">
    <%= f.submit 'Save', :class => 'btn btn-default' %>
  </div>
<% end %>
  

Комментарии:

1. Второй form_for предназначен для скрепки (в соответствии с их инструкциями). Облегченная загрузка изображения работала отлично до того, как я ввел поле категории.

2. но ваш form_for блок не содержит ничего, кроме отображения сообщений об ошибках. Я имею в виду <form role="form"> блок

3. Хорошо … это вообще не повлияло на функциональность моей отправки формы. `<form role=»form»> — это некоторая разметка для начальной загрузки.

4. Я хочу сказать: внутри блока нет кнопки отправки form_for !

5. Извините, если мой последний комментарий был непонятен… Удаление <form role="form"> не имело никакого эффекта, поэтому это не то, что вызывает мою текущую проблему.