【问题标题】:Getting ActiveRecord::AssociationTypeMismatch in PostsController#create in Rails App在 PostsController#create 在 Rails 应用程序中获取 ActiveRecord::AssociationTypeMismatch
【发布时间】:2016-04-22 11:32:39
【问题描述】:
Started POST "/posts" for ::1 at 2016-01-16 20:55:15 -0800 
Processing by PostsController#create as HTMLParameters: {"utf8"=>"✓", "authenticity_token"=>"RZREVs4Wy7ZWvo4u0xE5OmrawV2MYtxJNJZDfs+eQY8o2n1RthJsL5c1MklIpP+XlMGNbDYSD49fjna7Szq/1g==", "post"=>{"start"=>"2", "end"=>"1", "when(1i)"=>"2016", "when(2i)"=>"1", "when(3i)"=>"17", "when(4i)"=>"06", "when(5i)"=>"00"}}
User Load (0.2ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1  [["id", 1]]
Completed 500 Internal Server Error in 5ms (ActiveRecord: 0.2ms)
ActiveRecord::AssociationTypeMismatch (Location(#70172044981120) expected, got String(#70171989781540)):app/controllers/posts_controller.rb:8:in `create'

Full Trace activerecord(4.2.4)lib/active_record/associations/association.rb:218:inraise_on_type_mismatch!' activerecord (4.2.4) lib/active_record/associations/belongs_to_association.rb:12:in 'replace' activerecord (4.2.4) lib/active_record/associations/singular_association.rb:17:inwriter' activerecord (4.2.4) lib/active_record/associations/builder/association.rb:123:in start=' activerecord (4.2.4) lib/active_record/attribute_assignment.rb:54:inpublic_send' activerecord (4.2.4) lib/active_record/attribute_assignment.rb:54:in _assign_attribute' activerecord (4.2.4) lib/active_record/attribute_assignment.rb:41:inblock in assign_attributes' actionpack (4.2.4) lib/action_controller/metal/strong_parameters.rb:185:in each_pair' actionpack (4.2.4) lib/action_controller/metal/strong_parameters.rb:185:ineach_pair' activerecord (4.2.4) lib/active_record/attribute_assignment.rb:35:in assign_attributes' activerecord (4.2.4) lib/active_record/core.rb:564:ininit_attributes' activerecord (4.2.4) lib/active_record/core.rb:281:in initialize' activerecord (4.2.4) lib/active_record/inheritance.rb:61:innew' activerecord (4.2.4) lib/active_record/inheritance.rb:61:in new' activerecord (4.2.4) lib/active_record/persistence.rb:33:increate' app/controllers/posts_controller.rb:8:in `create'

post.rb

class Post < ActiveRecord::Base
  belongs_to :user
  belongs_to :start, :class_name => 'Location'
  belongs_to :end, :class_name => 'Location'

  validates :start, presence: true
  validates :end, presence: true
  validates :when, presence: true
  validates :user_id, presence: true
end

PostsController.rb

class PostsController < ApplicationController
  before_action :authenticate_user!
  def new
    @page_title = 'Add Post'
    @post = Post.new
  end
  def create
    @post = Post.create(post_params)
    # save the post
    if @post.save
        flash[:notice] = "Post Created"
        redirect_to posts_path
    else
        render 'new'
    end
  end

...

private
  def post_params
        params.require(:post).permit(:start, :end, :when, :description, :seats, :round_trip).merge(user_id: current_user.id)
  end

new.html.erb

<h2>Add New Post</h2>
<% if @post.errors.any? %>
    <% @post.errors.full_messages.each do |msg| %>
        <div class="alert alert-danger"><%= msg %> </div>
    <% end %>
<% end %>
<%= form_for @post do |f| %>
    <div class="form-group">
        <%= f.select :start_location, Location.all.collect {|x [x.city_name, x.id]}, {:include_blank => 'Select One'} %>
    </div>
   <div class="form-group">
            <%= f.select :end_location, Location.all.collect {|x| [x.city_name, x.id]}, {:include_blank => 'Select One'} %>
   </div>
   <div class="form-group">
       <%= f.label :When %><br />
       <%= f.datetime_select :when, :ampm => true, :minute_step => 15 %>
   </div>
    <button type="submit" class="btn btn-primary">Submit</button>
    <%=link_to "Cancel", root_path, class:'btn btn-default' %>
<% end %>

schema.rb

ActiveRecord::Schema.define(version: 20160117041612) do
  create_table "locations", force: :cascade do |t|
    t.string   "city_name"
    t.string   "state_name"
    t.string   "zip"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end
    create_table "posts", force: :cascade do |t|
      t.integer  "start"
      t.integer  "end"
      t.datetime "when"
      t.text     "description"
      t.integer  "seats"
      t.integer  "user_id"
      t.integer  "round_trip"
      t.datetime "created_at",  null: false
      t.datetime "updated_at",  null: false
    end

  create_table "users", force: :cascade do |t|
    t.string   "first_name",             default: "", null: false
    t.string   "last_name",              default: "", null: false
    t.integer  "location_id"
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true

end

我真的不知道为什么会遇到这个问题。帖子具有开始和结束位置。它还有一个 user_id,用户通过 devise 登录。请帮忙。

【问题讨论】:

  • 'end' 是 ruby​​ 中的保留关键字:您是否尝试将 :end 重命名为其他名称(例如 :end_location)?
  • 很遗憾,这不起作用。
  • 您也可以添加您的视图代码吗?我假设开始、结束和何时都是 Date 或 DateTime?
  • 我已经添加了我的视图代码。 start_location、end_location 和 when(类型为 DateTime)都在视图代码中设置或至少应该设置。

标签: ruby-on-rails ruby activerecord devise ruby-on-rails-4.2


【解决方案1】:

这不起作用,因为您将字符串传递给接受 Location 类实例的属性。由于 start 和 end 在模型中显示为类 Location,因此您的表单要么具有使用 fields_for 的嵌套属性,要么您可以选择一个位置。如果您有嵌套属性,则需要添加

accepts_nested_attributes_for :start, :end

到您的 Post 模型,然后更新 post_params 以获得正确的参数

def post_params
  params.require(:post).permit(:when, :description, :seats, :round_trip, start_attributes: [<fields in start>], end_attributes: [<fields in end>).merge(user_id: current_user.id)
end

如果您有选择位置的选择,那么您需要确保它们返回 start_id 和 end_id 作为参数并将您的 post_params 更新为

def post_params
  params.require(:post).permit(:start_id, :end_id, :when, :description, :seats, :round_trip).merge(user_id: current_user.id)
end

更新:
现在您已经发布了表单,我们可以看到您有选择。您的架构还显示您在帖子模型中具有整数形式的开始和结束。通常那些应该是 start_id 和 end_id 或者你需要使用 :foreign_key 选项和属于。此外,您的两个选择当前将参数作为 start_location 和 end_location 传递,这对于您的任何模型都不是有效参数。如果您修复 start_id/end_id 的命名,那么您将更新选择,如

<%= f.select :start_id, Location.all.collect {|x [x.city_name, x.id]}, {:include_blank => 'Select One'} %>

并更新您的 post_params 以允许 start_id 和 end_id。如果改为使用 :foreign_key 选项,那么它将是

<%= f.select :start, Location.all.collect {|x [x.city_name, x.id]}, {:include_blank => 'Select One'} %>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多