Rails ActiveRecord无法从多对多关联中找到方法

时间:2015-04-07 03:37:48

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

我的申请非常简单,我User可以有VideoVideo Tag多对多class User < ActiveRecord::Base def authenticate return true end end class Video < ActiveRecord::Base belongs_to :user end class Tag < ActiveRecord::Base end class VideoTag < ActiveRecord::Base belongs_to :video belongs_to :tag end

这是我的模特

<%= form_for(@video, html: { class: "directUpload" }, multipart: true) do |f| %>
  <% if @video.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@video.errors.count, "error") %> prohibited this user from being saved:</h2>

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

  <div class="field">
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </div>
  <div class="field">
    <%= f.label :path %><br>
    <%= f.file_field :path%>
  </div>
  <div class="field">
    <%= f.label :tags %><br>
    <%= f.text_field :tags %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

这是我的表格

class CreateVideos < ActiveRecord::Migration
  def change
    create_table :videos do |t|
      t.string :title
      t.string :path
      t.references :user, index: true

      t.timestamps null: false
    end
    add_foreign_key :videos, :users
  end
end

class CreateTags < ActiveRecord::Migration
  def change
    create_table :tags do |t|
      t.string :title

      t.timestamps null: false
    end
  end
end


class CreateVideoTags < ActiveRecord::Migration
  def change
    create_table :video_tags do |t|
      t.references :video, index: true
      t.references :tag, index: true

      t.timestamps null: false
    end
    add_foreign_key :video_tags, :videos
    add_foreign_key :video_tags, :tags
  end
end

但是我收到了这个错误。

  

视频中的NoMethodError#new Showing   /Users/user/MyProjects/video-archiver/app/views/videos/_form.html.erb   第24行提出的地方:

     

未定义的方法`标签&#39;对于#

我该如何解决这个问题?

更新

{{1}}

3 个答案:

答案 0 :(得分:2)

Video模型应如下所示:

class Video < ActiveRecord::Base
  belongs_to :user

  has_many :video_tags
  has_many :tags, through: :video_tags
end

答案 1 :(得分:1)

首先,关系应设置如下。

class User < ActiveRecord::Base
    has_many :videos

    def authenticate
        return true
    end
end

这是因为如果视频属于用户,并且您说用户有很多视频,那么这种关系就更有意义了。虽然伦尔并没有完全回答这个问题,但不幸的是,我也是如此。他的答案也是正确的。

我对你的问题的唯一答案是你应该使用:tag not:第24行的标签。

如果没有更多信息,我认为我无法提供更多帮助。

答案 2 :(得分:1)

所以这就是我看到的代码问题。以下是有问题的代码部分。

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

原因是:标签不是数据库中的字段。它只是一个对象。换句话说,请查看下面的迁移。

create_table :videos do |t|
      t.string :title
      t.string :path

两者:title和:path现在是数据库中用于视频表的列。但是,数据库中没有:tags字段的列。数据库中的标记是数据库的对象/行,不代表单个字段。每个标签都有:标题......

create_table :tags do |t|
      t.string :title

但是没有字段:tags或:tag或类似的东西。这就是您收到错误NoMethodError的原因。 Ruby On Rails的功能,或者更具体地说是Active Records的功能,是链接数据库列到模型中的getter和setter方法。因此,您的视频模型为您的:标题和:在后台设置的路径字段预先制作了setter和getters,而无需亲自查看。这就是你的表单可以看到你正在填写一个@video对象,你的:title和:path被神奇地链接到那些getter和setter。对于在RoR中具有模型的任何表的所有列都会发生这种情况。

因此,由于您的数据库中没有一个名为:tags的可编辑字段,因此Ruby On Rails没有setter和getter来绑定到您的html表单。因此,当您尝试调用它时,它会抱怨并说它无法找到RoR设计应该存在的方法。

所以,我给你的建议是按照lunr和我的建议重新设计你的数据库布局,然后在做的时候记住上面的内容。 Ruby On Rails的这一部分并不是一直都很清楚。它在文档中是正确的,但需要一些时间来找到并真正包裹你,所以我见过的大多数人都会在早期犯这个错误。一旦你对它感到满意,那真是太棒了。

希望这有帮助!