我希望设置一个用户可以创建帖子并标记该帖子的关系。该帖子和那些标签属于该用户。
过去三天我一直试图调试这个。我不知道为什么当我保存我的帖子时,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
答案 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)
希望有所帮助:)