无法在Rails 4 many_to_many关联中呈现复选框

时间:2015-04-07 05:45:43

标签: ruby-on-rails

我在many_to_manyCategories之间建立Articles关联,在Rails 4应用中使用has_and_belongs_to_many

以下是相应的迁移和类:

class CategoriesArticles < ActiveRecord::Migration
  def change
    create_table :categories_articles, id: false do |t|
      t.belongs_to :category, index: true
      t.belongs_to :article, index: true
    end
    add_index :categories_articles, [:category_id, :article_id]
  end
end

class Category < ActiveRecord::Base
  has_and_belongs_to_many :articles
end

class Article < ActiveRecord::Base
  has_and_belongs_to_many :categories
end

当用户创建新文章时,我只想让他或她选择他/她想要与新文章关联的类别。我希望用户能够使用复选框选择这些类别。

这里是ArticlesController

class ArticlesController < ApplicationController
  before_action :set_article, only: [:show, :edit, :update, :destroy]
  before_action :authenticate_user!, only: [:new, :create, :edit, :destroy, :update]
  before_action :verify_own_article, only: [:destroy]
  respond_to :html

  def index
    if user_signed_in?
      @articles = current_user.article_feed
      # TODO: if there are too few articles on a user's feed, we want to display more articles
    else
      @articles = Article.all
    end
    @articles = @articles.page(params[:page] || 1).per(12)
    respond_with(@articles)
  end

  def show
    respond_with(@article)
  end

  def new
    @categories = Category.all
    @article = Article.new
    respond_with(@article)
  end

  def edit
    if current_user.articles.find_by_id(params[:id]).nil?
      flash[:notice] = "You do not have permission to edit this article."
      redirect_to @article
    end
  end

  def create
    # Creates article object with current_user_id, initial_comment, and URL
    @article = current_user.articles.build(article_params)

    # Uses Pismo (gem) to grab title, content, photo of URL
    @article.populate_url_fields
    if @article.save
      flash[:success] = "Article created!"

      # Might need to change the location of this redirect
      redirect_to root_url
    else
      flash[:notice] = "Invalid article."
      redirect_to new_article_path
    end

  end

  def update
    @article.update(article_params)
    flash[:notice] = "Article successfully updated."
    respond_with(@article)
  end

  def destroy
    if @article
      @article.destroy
      flash[:notice] = "Article successfully destroyed."
    else
      flash[:notice] = "You do not have permission to delete this article."
    end
    # TODO: change this to another redirect location
    redirect_to root_path
  end

  private
    def set_article
      @article = Article.find(params[:id])
    end

    def article_params
      params.require(:article).permit(:url, :title, :datetime, :content, :photo, :initial_comment)
    end

    # Ensure that a signed in user can only delete articles that they have posted
    def verify_own_article
      @article = current_user.articles.find_by_id(params[:id])
    end
end

这里是文章new.html.erb视图:

<h1>New article</h1>

<%= render 'form' %>

<%= link_to 'Back', articles_path %>

...和form部分:

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

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

  <div class="field">
    <%= f.label :url %><br>
    <%= f.text_field :url %>
  </div>
  <div class="field">
    <%= f.label :initial_comment %><br>
    <%= f.text_field :initial_comment %>
  </div>


  <% @categories.each do |t| %>
    <div class="field">
      <%= f.label t.name %>
      <%= f.check_box "categories[#{t.id}]" %>
      <br />
    </div>
  <% end %>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

然而,这对我来说是错误的,特别是行:

<% @categories.each do |t| %>
        <div class="field">
          <%= f.label t.name %>
          <%= f.check_box "categories[#{t.id}]" %>
          <br />
        </div>
      <% end %>

具体来说,它告诉我:

undefined method 'categories[1]' for #<Article:0x007f401193d520>。我该如何解决?感谢。

1 个答案:

答案 0 :(得分:0)

我注意到您的联接表名为

create_table :categories_articles, id: false do |t|

名称必须按字母顺序排列。

create_table :articles_categories, id: false do |t|

我的选择是Rails无法找到您的联接表。这意味着它调用@ article.categories时的表单无法找到它需要的内容。如果你调用@ category.articles会发生同样的情况(即:能够找到连接表与对象的任意顺序无关)。

请参阅我对this question

的回答