【问题标题】:Rails 4 - Many to many categories won't save to databaseRails 4 - 多对多类别不会保存到数据库
【发布时间】:2014-02-07 10:58:17
【问题描述】:

我有 3 个表,分别称为 pin(帖子)、genres(类别)和genre_pin(pin 和流派之间的多对多,因为 pin 可以有多种流派)。

我正在尝试构建创建表单,这将允许用户在 pin 上选择任意数量的流派并保存/创建。创建工作正常,没有错误,但它没有将任何关系记录保存到genre_pin 表中。我很确定我可能在这里遗漏了一些非常明显的东西。

我使用术语“pins”和“genres”,但您可以将它们视为与“posts”和“categories”相同。

引脚模型

class Pin < ActiveRecord::Base

    belongs_to :user
    belongs_to :type
    has_many :replies
    has_many :genre_pins
    has_many :genres, :through => :genre_pins

    accepts_nested_attributes_for :genres, allow_destroy: true, reject_if: proc { |genre| genre[:id].blank? }

    validates :user_id, presence: true
    validates :type_id, presence: true
    validates :title, presence: true
    validates :description, presence: true

end

体裁模型

class Genre < ActiveRecord::Base

    has_many :genre_pins
    has_many :pins, :through => :genre_pins

    validates :title, presence: true

end

GenrePin 模型

class GenrePin < ActiveRecord::Base

    belongs_to :pin
    belongs_to :genre

    validates_uniqueness_of :pin_id, :scope => :genre_id

end

接下来,在我的 pin#new 视图中,我有以下表格:

固定新视图

<%= form_for :pin, url: pins_path do |f| %>

    <div class="small-12 columns">
        <%= f.label :title %>
        <%= f.text_field :title %>
    </div>

    <div class="small-12 columns">
        <%= f.label :description %>
        <%= f.text_area :description, :rows => 10 %>
    </div>

    <div class="small-12 columns">
        <%= f.label :type %>
        <%= f.collection_select :type_id, Type.order(:title), :id, :title, include_blank: false %>
    </div>

    <div class="small-12 columns">
        <%= f.label :genres %>
        <%= f.collection_select :genre_ids, Genre.order(:title), :id, :title, {}, { :multiple => true } %>
    </div>

    <div class="small-12 columns">
        <%= f.submit "Create Pin", :class => "button" %>
    </div>

<% end %>

视图运行良好,可以从流派表中获取可用的流派。但是,当我去保存表单时,记录(pin)被创建,但与流派的关系却没有。我在这里想念什么?没有错误被抛出,只是什么都没有发生。我假设 Rails 应该通过与流派关联的 pin 来创建这些 PinGenre 记录。

引脚控制器(创建)

def create

    @pin = Pin.new(pin_params)
    @pin.user_id = current_user.id
    @pin.save

    if @pin.save
        flash[:success] = "Pin successfully created"
        redirect_to @pin
    else
        flash[:warning] = @pin.errors.full_messages.to_sentence
        redirect_to :action => "new"
    end

end

private

        def pin_params

            params.require(:pin).permit(:title, :description, :type_id, :genre_ids)

        end

我需要在此处采取进一步的步骤吗?记录需要我自己明确创建吗?

感谢您的帮助和耐心。我希望我已经清楚地阅读了这篇文章。 迈克尔。

Schema.rb

ActiveRecord::Schema.define(version: 0) do

  create_table "genre_pins", force: true do |t|
    t.integer "pin_id"
    t.integer "genre_id"
  end

  create_table "genres", force: true do |t|
    t.string "title", null: false
  end

  create_table "pins", force: true do |t|
    t.integer  "user_id",                                          null: false
    t.string   "title",       limit: 160,                          null: false
    t.text     "description",                                      null: false
    t.decimal  "latitude",                precision: 10, scale: 8
    t.decimal  "longitude",               precision: 11, scale: 8
    t.datetime "created_at"
    t.datetime "updated_at"
    t.datetime "deleted_at"
    t.integer  "type_id",                                          null: false
  end

  create_table "profiles", force: true do |t|
    t.integer  "user_id",                                          null: false
    t.string   "first_name",                                       null: false
    t.string   "last_name",                                        null: false
    t.string   "gender"
    t.string   "email"
    t.text     "bio"
    t.decimal  "latitude",                precision: 10, scale: 8
    t.decimal  "longitude",               precision: 11, scale: 8
    t.string   "image",      limit: 2000
    t.datetime "updated_at"
    t.datetime "created_at"
    t.datetime "deleted_at"
  end

  create_table "replies", force: true do |t|
    t.integer  "pin_id",     null: false
    t.integer  "user_id",    null: false
    t.text     "reply",      null: false
    t.datetime "updated_at"
    t.datetime "created_at"
    t.datetime "deleted_at"
  end

  create_table "saves", force: true do |t|
    t.integer  "pin_id",     null: false
    t.integer  "user_id",    null: false
    t.datetime "updated_at"
    t.datetime "created_at"
    t.datetime "deleted_at"
  end

  create_table "settings", force: true do |t|
    t.integer  "user_id",        null: false
    t.boolean  "show_email",     null: false
    t.boolean  "show_telephone", null: false
    t.integer  "timezone",       null: false
    t.datetime "updated_at"
    t.datetime "created_at"
    t.datetime "deleted_at"
  end

  create_table "types", force: true do |t|
    t.string "title", null: false
  end

  create_table "users", force: true do |t|
    t.string   "provider",         limit: 45,   null: false
    t.string   "provider_id",      limit: 45,   null: false
    t.string   "oauth_token",      limit: 1000
    t.datetime "oauth_expires_at"
    t.datetime "updated_at"
    t.datetime "created_at"
    t.datetime "deleted_at"
  end

end

生成的查看源代码

<form accept-charset="UTF-8" action="/pins" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /><input name="authenticity_token" type="hidden" value="3VO3kVR/62JFf6dJs+yyPTPvYJb3fsUSLRFljSE0Jdk=" /></div>

        <div class="small-12 columns">
            <label for="pin_title">Title</label>
            <input id="pin_title" name="pin[title]" type="text" />
        </div>

        <div class="small-12 columns">
            <label for="pin_description">Description</label>
            <textarea id="pin_description" name="pin[description]" rows="10">
</textarea>
        </div>

        <div class="small-12 columns">
            <label for="pin_type">Type</label>
            <select id="pin_type_id" name="pin[type_id]"><option value="2">Available</option>
<option value="1">Wanted</option></select>
        </div>

        <div class="small-12 columns">
            <label for="pin_genres">Genres</label>
            <input name="pin[genre_ids][]" type="hidden" value="" /><select id="pin_genre_ids" multiple="multiple" name="pin[genre_ids][]"><option value="5">Ambient</option>
<option value="4">Electronic</option>
<option value="2">Indie</option>
<option value="3">Jazz</option>
<option value="6">Metal</option>
<option value="1">Rock</option></select>
        </div>

        <div class="small-12 columns">
            <input class="button" name="commit" type="submit" value="Create Pin" />
        </div>

</form>

【问题讨论】:

  • 你能发布你的 pin 控制器的“新”方法吗?
  • pin 控制器中的“新”操作只是空白,因为它所做的只是加载视图。
  • 你能发布你的 'genre_pin' Active Record 迁移文件吗?
  • 我的 db/migrate 文件夹是空的?
  • 是的!该genre_pin schema.rb

标签: ruby-on-rails ruby ruby-on-rails-4


【解决方案1】:

你需要告诉你的控制器 'genre_ids` 应该是一个数组:

params.require(:pin).permit(:title, :description, :type_id, genre_ids: [])

但是我希望您会收到另一个错误(未知属性gener_ids)。如果发生这种情况,请告诉我。

【讨论】:

  • 我现在收到错误“字段 ID 没有默认值”。请求参数显示:{"utf8"=>"✓", "authenticity_token"=>"3VO3kVR/62JFf6dJs+yyPTPvYJb3fsUSLRFljSE0Jdk=", "pin"=>{"title"=>"aaaa", "description"=> "aaa", "type_id"=>"2", "genre_ids"=>["", "4", "3"]}, "commit"=>"创建 Pin", "action"=>"create" , "控制器"=>"引脚"} .似乎有一个空白值...可能会绊倒它吗?不知道为什么会这样。感觉我们越来越近了。谢谢。
  • 对,我的 DB 中的genre_pins 表的 ID 字段未设置为自动增量。现在我在数据库中改变了这个,一切都很好,正如预期的那样!非常感谢。我会接受这个作为答案。
  • 出于好奇 - 您是否在 Pin 模型中定义了 'genre_ids=' 方法?没有它我无法理解它是如何工作的。 :)
  • 不,我不这么认为。整个 Pin 模型如上图所示。我正在使用 Rails 4 是否与它有关? Pins 连接到genre_pins,流派连接到genre_pins。也许它“只知道”?
猜你喜欢
  • 2020-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-07
相关资源
最近更新 更多