【问题标题】:form for object in two HABTM relationships, Rails 3两个HABTM关系中的对象形式,Rails 3
【发布时间】:2013-02-13 19:58:14
【问题描述】:

我正在尝试通过构建网站来学习 Ruby on Rails。用户可以添加内容:帖子和图片。帖子和图片可以有一个或多个标签。我希望每个关系都是 HABTM,这样我就可以通过特定标签轻松访问帖子、图片,反之亦然。

我正在尝试制作表单来为帖子和图片添加标签。当我提交任一表单时,我得到的错误是:

POST http://localhost:8080/post/1/tags 500 (Internal Server Error)

当我查看返回的对象时(这两种形式都是一样的):

#Tag id: nil, name: "asdf"> 在 '@tag.save' 行上的未定义方法 `post_id'

我已尝试将 post_id、picture_id 添加到 Tag 的 attr_accesible;没有骰子。 谢谢你的帮助!我觉得我只是缺少一些小东西。

我的模型:

class Tag < ActiveRecord::Base
  attr_accessible :name

  has_and_belongs_to_many :pictures
  has_and_belongs_to_many :posts
  validates :name, :presence => true
  validates :name, :uniqueness =>  { :scope => :post_id }
  validates :name, :uniqueness => { :scope => :picture_id }
end

class Post < ActiveRecord::Base
  attr_accessible :content, :title

  belongs_to :user
  has_and_belongs_to_many :tags
end

class Picture < ActiveRecord::Base
      attr_accessible :image, :name

      belongs_to :user
      has_and_belongs_to_many :tags
end

迁移:

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

    create_table :pictures_tags, :id => false do |t|
        t.references :picture, :tag
    end
  end
end

class CreatePostsTags < ActiveRecord::Migration
    def change
    create_table :posts_tags, :id => false do |t|
        t.references :post, :tag
    end
  end
end

在我看来:

<%= form_for([@post, @post.tags.build]) do |f| %>
    <%= f.label 'tag' %>
    <%= f.text_area :name %>
    <%= f.submit %> 
<% end %>

<% current_user.pictures.each do |p|
<%= form_for([p, p.tags.build], :remote => true) do |f| %>
    <%= f.text_area :name %>
    <%= f.submit 'add tag' %>
<% end %>   
<% end %>

在我的标签控制器中:

def tag_post
    authenticate_user!
    @post = Post.find(params[:id])
    @tag = @post.tags.build(params[:tag])
    @tag.save
    redirect_to edit_post_path(@post)
end

def tag_picture
    authenticate_user!
    @picture = Picture.find(params[:id])
    @tag = @state.picture.build(params[:tag])
    @tag.save
            redirect_to edit_picture_path(@picture)
end

Routes.rb:

post '/posts/:id/tags' => 'tags#tag_post', :as => :tag_post
post '/flow/:id/tags' => 'tags#tag_picture', :as => :tag_picture

耙路线:

                   posts GET    /posts(.:format)                            posts#index
                         POST   /posts(.:format)                            posts#create
                new_post GET    /posts/new(.:format)                        posts#new
               edit_post GET    /posts/:id/edit(.:format)                   posts#edit
                    post GET    /posts/:id(.:format)                        posts#show
                         PUT    /posts/:id(.:format)                        posts#update
                         DELETE /posts/:id(.:format)                        posts#destroy
        new_user_session GET    /users/sign_in(.:format)                    devise/sessions#new
            user_session POST   /users/sign_in(.:format)                    devise/sessions#create
    destroy_user_session DELETE /users/sign_out(.:format)                   devise/sessions#destroy
           user_password POST   /users/password(.:format)                   devise/passwords#create
       new_user_password GET    /users/password/new(.:format)               devise/passwords#new
      edit_user_password GET    /users/password/edit(.:format)              devise/passwords#edit
                         PUT    /users/password(.:format)                   devise/passwords#update
cancel_user_registration GET    /users/cancel(.:format)                     devise/registrations#cancel
       user_registration POST   /users(.:format)                            devise/registrations#create
   new_user_registration GET    /users/sign_up(.:format)                    devise/registrations#new
  edit_user_registration GET    /users/edit(.:format)                       devise/registrations#edit
                         PUT    /users(.:format)                            devise/registrations#update
                         DELETE /users(.:format)                            devise/registrations#destroy
                    root        /                                           flow#flow
                    root        /                                           flow#home
             posts_index GET    /ramblin(.:format)                          posts#index
               post_tags POST   /posts/:id/tags(.:format)                   tags#tag_post
              picture_tags POST   /flow/:id/tags(.:format)                  tags#tag_picture
            create_picture POST   /flow(.:format)                             pictures#create
                  search POST   /flow/search(.:format)                      flow#flow

【问题讨论】:

  • 请运行rake routes 并给我们输出
  • 在问题底部添加了耙路线。

标签: ruby-on-rails ruby-on-rails-3 has-and-belongs-to-many form-for


【解决方案1】:

问题出在

  validates :name, :uniqueness =>  { :sscope => :post_id }
  validates :name, :uniqueness => { :scope => :picture_id }

因为这些方法期望 tag 模型具有存储在 posts_tags 中的 post_idpicture_id 属性

【讨论】:

  • 非常感谢。有了这种理解,似乎没有办法使用内置的 Rails 验证来进行这种验证?我将编写一个自定义验证-
【解决方案2】:

查看通过运行rake routes 输出的路由。有这样一行:

post_tags POST    /posts/:id/tags(.:format)    tags#tag_post

这表明路径必须是posts(复数)而不是post(单数)。

所以,你应该改为发帖到

/posts/1/tags

顺便说一句,我知道你说你正在学习 Rails,所以你从头开始构建一个标记系统真是太好了 - 但稍后你可能想看看这个很棒的 gem acts as taggable on。这超级简单有趣。这里有一个rails casts,可以很好地完成标记。

【讨论】:

  • 谢谢你!尽管这不会导致直接问题,但我删除的代码仍然存在问题。谢谢!!感谢您提出“作为可标记的行为”的建议,我看到了那个宝石,但就像您说的那样,认为从头开始实施标记将是一种有用的学习设备:)
猜你喜欢
  • 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
相关资源
最近更新 更多