0

我在 Rails 中设置了 2 个模型:

class Category < ActiveRecord::Base
  attr_accessible :name
  has_many :platforms
end

class Platform < ActiveRecord::Base
    attr_accessible :name, :url, :country
    validates :name, :presence => true, :length => { :minimum => 5 }
    validates :url, :presence => true, :length => { :minimum => 5 }
    belongs_to  :categories
end

这是我的平台控制器:

class PlatformsController < ApplicationController
  # GET /platforms
  # GET /platforms.json
  def index
    @platforms = Platform.all
    @categories = Category.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @platforms }
    end
  end

  # GET /platforms/1
  # GET /platforms/1.json
  def show
    @platform = Platform.find(params[:id])
    @categories = Platform.categories

    respond_to do |format|
      format.html # show.html.erb
      format.json { render json: @platform }
    end
  end

  # GET /platforms/new
  # GET /platforms/new.json
  def new
    @platform = Platform.new
    @categories = Category.all

    respond_to do |format|
      format.html # new.html.erb
      format.json { render json: @platform }
    end
  end

  # GET /platforms/1/edit
  def edit
    @platform = Platform.find(params[:id])
    @categories = Category.find(:all)
  end

  # POST /platforms
  # POST /platforms.json
  def create
    @platform = Platform.new(params[:platform])
    #@categories = Category.new(params[:name])
    @categories = @platform.categories.create(params[:categories])

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

  # PUT /platforms/1
  # PUT /platforms/1.json
  def update
    @platform = Platform.find(params[:id])
    @categories = Category.find(:all)

    respond_to do |format|
      if @platform.update_attributes(params[:platform])
        format.html { redirect_to @platform, notice: 'Platform was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: "edit" }
        format.json { render json: @platform.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /platforms/1
  # DELETE /platforms/1.json
  def destroy
    @platform = Platform.find(params[:id])
    @platform.destroy

    respond_to do |format|
      format.html { redirect_to platforms_url }
      format.json { head :no_content }
    end
  end
end

我不明白我做错了什么,但是当我尝试使用时,它没有正确地将类别分配给平台,也在平台索引视图中:

<%= platform.categories  %>

它给了我错误找不到带有 id=“和这里的相应 id”的类别

我真的很困惑,因为我遵循了这个教程。

我使用 Rails 3.2.8

4

1 回答 1

1

没有您的观点,我无法确定您正在尝试做什么。最重要的是,你的 params[:categories] 哈希中有什么?给定名称,听起来您打算将其划分为多个类别。但是,您的代码编写得好像您打算将其作为一组描述一个属性的属性Category

Since I can't say for sure what you want to do, I'll answer your question by explaining what you are doing. Maybe that will help you figure out how to fix it.

Your create code currently looks like this:

# POST /platforms
# POST /platforms.json
def create
  @platform = Platform.new(params[:platform])
  #@categories = Category.new(params[:name])
  @categories = @platform.categories.create(params[:categories])

The first line creates the new Platform and is easy. Skipping over the comment to the third line. This is probably what's tripping you up.

You are selecting the associations for your newly created Platform and trying to create a new category with attributes as stored in the params[:categories] hash. I'm afraid this is not allowed. (I think it throws an ActiveRecord::RecordNotSaved exception, but I could be wrong.) You can not create on a @platform which hasn't been persisted yet. Instead, I think you want build.

Here is the relevant documentation: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

The difference between create and build is that build just sets up the association without actually saving it to the database yet. create saves it immediately. The nice thing about build is that you don't actually have to save it yourself. It tags along for free when you call @platform.save or @platform.update_attributes. Also, save is automatically wrapped in a transaction, so it won't create the new Category if it fails to create the new Platform for whatever reason.

The next interesting thing is that you are assigning the result of your create to @categories. I don't think this is what you want either. You don't need to save the new Category because it tags along with your @platform. However, if the save of the platform fails, then you are going to re-render your new view with this value of @categories whereas in new you set @categories = Category.all. This could certainly cause some confusion on the new view after a failed create.

In summary, I think your create code should look something like the following.

# POST /platforms
# POST /platforms.json
def create
  @platform = Platform.new(params[:platform])
  @platform.categories.build(params[:categories])

  respond_to do |format|
    if @platform.save
      format.html { redirect_to @platform, notice: 'Platform was successfully created.' }
      format.json { render json: @platform, status: :created, location: @platform }
    else
      @categories = Category.all
      format.html { render action: "new" }
      format.json { render json: @platform.errors, status: :unprocessable_entity }
    end
  end
end

If you're params[:categories] is not a hash of category attributes and is actually a comma delimited string of category names, then you would want to do something like the following instead of my second line above:

params[:categories].split(",").each do |category|
  @project.categories.build(name: category)
end

You may also want to check out accepts_nested_attributes_for which can DRY out your controller even more. http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

I hope that helps.

于 2012-12-05T00:42:46.733 回答