【问题标题】:How to get name of model linked from another model in Rails?如何获取从 Rails 中的另一个模型链接的模型名称?
【发布时间】:2012-11-05 13:58:58
【问题描述】:

我在 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

【问题讨论】:

  • 我也得到了这个:ActiveModel::MassAssignmentSecurity::Error in PlatformsController#update 无法批量分配受保护的属性:category_id
  • 一个平台可以分多类吗?如果是这样,您可能想查看has_and_belongs_to association
  • 不,一个平台只能属于1个类别,但一个类别可以有多个平台。
  • 好的,那么首先您需要在您的 Product 模型中修复 Category 关联。 belongs_to: category 属于关联的都是单数形式。
  • 此外,由于belong_to 关联,您无法从平台实例创建类别。但是,由于has_many 关联,您可以从类别创建平台。

标签: ruby-on-rails model controller associations


【解决方案1】:

没有您的意见,我无法确定您到底想要做什么。最重要的是,你的 params[:categories] 哈希中有什么?给定名称,听起来您打算将其划分为多个类别。但是,您的代码编写时就好像您希望它是一组描述一个 Category 的属性。

由于我无法确定您想要做什么,我将通过解释您正在做什么来回答您的问题。也许这会帮助你弄清楚如何解决它。

您的create 代码目前如下所示:

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

第一行创建了新的Platform,很简单。跳过评论到第三行。这可能是让你绊倒的原因。

您正在为新创建的Platform 选择关联,并尝试使用存储在params[:categories] 哈希中的属性创建一个新类别。恐怕这是不允许的。 (我认为它会引发ActiveRecord::RecordNotSaved 异常,但我可能是错的。)您不能在尚未持久化的@platform 上使用create。相反,我认为你想要build

以下是相关文档: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

createbuild 之间的区别在于build 只是设置了关联,而没有实际将其保存到数据库中。 create 立即保存。 build 的好处是您实际上不必自己保存它。当您致电@platform.save@platform.update_attributes 时,它会免费标记。此外,save 会自动包装在事务中,因此无论出于何种原因无法创建新的Platform,它都不会创建新的Category

下一个有趣的事情是您将创建的结果分配给@categories。我认为这也不是你想要的。您不需要保存新的Category,因为它会与您的@platform 一起标记。但是,如果平台的save 失败,那么您将使用@categories 的值重新渲染您的new 视图,而在new 中您设置@categories = Category.all。在create 失败后,这肯定会导致new 视图出现一些混乱。

总之,我认为您的create 代码应该类似于以下内容。

# 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

如果您params[:categories] 不是类别属性的散列,实际上是一个以逗号分隔的类别名称字符串,那么您可能需要执行以下操作,而不是我上面的第二行:

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

您可能还想查看accepts_nested_attributes_for,它可以让您的控制器更加干燥。 http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html

希望对你有帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-12
    • 1970-01-01
    • 2013-11-06
    • 2011-03-26
    • 1970-01-01
    • 2016-05-10
    • 1970-01-01
    相关资源
    最近更新 更多