我的协会有什么问题?

时间:2012-11-06 17:55:15

标签: ruby-on-rails ruby-on-rails-3 activerecord associations model-associations

我希望设置一个用户可以创建帖子并标记该帖子的关系。该帖子和那些标签属于该用户。

过去三天我一直试图调试这个。我不知道为什么当我保存我的帖子时,user_id不会填充在Tag模型中。我将user_id添加到Tag模型中。

我提前为过多的代码道歉。

用户 - has_many帖子; has_many标签

发布 - belongs_to用户; has_many标签; has_many标签通过标签

标签 - 有很多标签; has_many通过标记发布帖子; belongs_to用户

标记 - belongs_to post; belongs_to标签

ActiveRecord::Schema.define(:version => 20121031012555) do

  create_table "posts", :force => true do |t|
    t.integer  "user_id"
    t.string   "summary"
    t.datetime "created_at",  :null => false
    t.datetime "updated_at",  :null => false
  end

  create_table "taggings", :force => true do |t|
    t.integer  "post_id"
    t.integer  "tag_id"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end

  add_index "taggings", ["post_id"], :name => "index_taggings_on_post_id"
  add_index "taggings", ["tag_id"], :name => "index_taggings_on_tag_id"

  create_table "tags", :force => true do |t|
    t.string   "name"
    t.integer  "user_id"
    t.datetime "created_at", :null => false
    t.datetime "updated_at", :null => false
  end

  create_table "users", :force => true do |t|
    t.string   "username"
    t.string   "email"
    t.string   "crypted_password"
    t.string   "password_salt"
    t.string   "persistence_token"
    t.datetime "created_at",        :null => false
    t.datetime "updated_at",        :null => false
    t.string   "role"
  end

end

在帖子模型中:

def tag_ids=(tags_string)
    self.taggings.destroy_all

    tag_names = tags_string.split(",").collect{|s| s.strip.downcase}.uniq
    tag_names.each do |tag_name|
      tag = Tag.find_or_create_by_name(tag_name)
      tagging = self.taggings.new
      tagging.tag_id = tag.id
    end
end

2 个答案:

答案 0 :(得分:1)

如果我遗漏了某些内容,我会道歉,但看起来你在创建时没有将用户ID传递给代码。使用rails 3,您可以为多个属性执行find_or_create_by,如下所示:

tag = Tag.find_or_create_by_name_and_user_id(tag_name, user_id)

此外,如果您只想构建Tag对象,但不立即将其保存到DB,则可以使用“find_or_initialize_by ...”方法,如下所示:

tag = Tag.find_or_initialize_by_name_and_user(tag_name, user)

确保您的代码模型已经attr_accessible :user_id,如果它还没有。

更新:抱歉,我刚刚重新阅读了您的问题,并且您声明已将user_id传递给代码模型。但是我在你提供的代码中没有看到;那会发生在哪里?

更新#2 根据注释线程,您的参数映射不包含user_id;当然,这是因为参数映射是从表单输入构建的,显然不包含用户的输入。

我假设在创建帖子时,它应该与当前登录的用户相关联。我还假设您在某处可以使用当前登录用户的引用,我将调用@current_user。

由于您希望在一个原子操作中创建帖子和关联标签,您可以做的一件事就是将当前用户添加到参数图的副本中,如下所示:

post_params = params.clone.store(:user=>@current_user)
@post = Post.new(post_params)

可能有更好的方法,但这应该有效。请注意,您可能不需要复制参数映射;我管理员我不确定在这种情况下最佳做法是什么。

无论如何,希望有所帮助。

更新3 由于Ruby哈希按照插入键的顺序进行迭代,因此svn的tag_ids是在他的user_id进入Post模型之前设置的。为了解决这个问题,svn颠倒了我之前建议的顺序,并确保在任何其他值之前插入:user用户密钥。这是一个可能的解决方案(从svn的主旨(https://gist.github.com/4027807)修改):

post_params = {:user => current_user}.merge!(params[:post].clone)
@post = Post.new(post_params)

答案 1 :(得分:0)

在控制器中的行之前

@post = Post.new(params[:post])

添加以下行

@post = Post.new(:user_id => <assign your required user_id>)

这将使新的post对象在其instace方法中使用user_id 然后你就可以在线下成功使用了

tag = Tag.find_or_create_by_name_and_user_id(tag_name, user_id)

希望有所帮助:)