Rails:ActiveRecord :: AssociationTypeMismatch错误

时间:2017-03-31 16:59:50

标签: ruby-on-rails ruby activerecord

是否可以在表上包含以下两列,并使用active_record保存它们:

  • user_name_id(这是一个协会)
  • user_name(只是文字)

演示尝试保存关联字段user_name_id和文本字段user_name

以下是模型:

#app/models/blog.rb
class Blog < ApplicationRecord
  belongs_to :user_name
end

#app/models/user_name.rb
class UserName < ApplicationRecord
  has_many :blogs
end

表格:

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

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

  <div class="field">
    <%= f.label :user_name %>
    <%= f.text_field :user_name %>
  </div>

  <div class="field">
    <%= f.label :user_name_id %>
    <%= f.collection_select :user_name_id, UserName.all, :id, :name %>
  </div>

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

强大的参数:

def blog_params
  params.require(:blog).permit(:user_name, :user_name_id)
end

当我提交表单以创建新的blog时,它会出错。 params hash看起来不错:

“blog”=>{“user_name_id"=>"1", “user_name"=>”foo”}

但是我收到以下错误:

  

的ActiveRecord :: AssociationTypeMismatch   用户名(#70119900697480)预期,得到字符串(#70119800086640)

更新:我理解这一点,理想情况是:其中一个属性的列名应该更改。尽管如此:是否可能使用rails执行此操作?需要什么?

3 个答案:

答案 0 :(得分:2)

从上面的答案中可以明显看出这个问题 - 将user_name属性更改为其他内容。

作为最后的手段,这可能是一个糟糕的建议,但您甚至可以尝试声明您正在使用的属性:

class Blog < ApplicationRecord
  belongs_to :user_name, through: :user_name_id
end

但同样,您关联记录的原因是,您可以通过关联随时调用user_name,并获取存储在那里的所有信息。这意味着,您不需要将user_name与blog一起存储...因为您已经通过了user_name关联。

答案 1 :(得分:1)

  1. 如果您已使用belongs_to'user_name',则根本不应使用'user_name'字段。
  2. 请不要调用Model'UserName'这不好,也许这是UserProfile或只是用户?
  3. 您确定要为您的博客缓存user_name吗?如果用户将更改他的名字,将会产生许多问题。如果你想要为博客缓存user_name你可以重命名'user_name_cached'上的列并在'UserName'上更新它将在before_save回调上更新。
  4. 作者更新的更新:

    belongs_to :your_new_belons_to_name, class_name: 'NameUser', foreign_key: 'name_user_id'

答案 2 :(得分:0)

当你这样做时:

belongs_to :user_name

ActiveRecord假设Blog有一个属性user_name_id(它看起来像你一样 - 到目前为止,非常好)。如Guide中所述,您还会获得一个setter方法user_name=,该方法希望您将UserName实例传递给它。

当您执行以下操作时:

Blog.new(“user_name_id"=>"1", “user_name"=>”foo”)

ActiveRecord期望user_name成为类UserName的实例。但你刚刚传递了String。这正是错误告诉你的。

另外,我同意Alexey。我不知道为什么你会在user_name上坚持Blog(作为一个字符串)。如果班级UserName具有name属性,那么您可以随时执行以下操作:

blog.user_name.name

我也同意Alexey的观点,UserName是一个奇怪的类名。 Alexey关于命名的建议很好,所以请考虑一下。