我有一个有博客功能的应用程序。最初,当我设置这个帖子时,帖子由标题、正文、关键字和图像链接组成。我希望能够根据关键字过滤帖子,我认为最干净的方法是将关键字移动到自己的表中,并将这两个表关联起来。因此每个帖子可以有多个关键字,每个关键字可以有多个帖子。
我为关键字创建了一个迁移和模型。
class CreateKeywords < ActiveRecord::Migration[6.1]
def change
create_table :keywords do |t|
t.string :keyword
t.timestamps
end
end
endclass Keyword < ApplicationRecord
has_and_belongs_to_many :posts
end我将其与posts表关联,并更改了posts模型。
class CreatePostsKeywordsJoinTable < ActiveRecord::Migration[6.1]
def change
create_join_table :posts, :keywords do |t|
t.index [:post_id, :keyword_id]
t.index [:keyword_id, :post_id]
end
end
endclass Post < ApplicationRecord
belongs_to :user
has_and_belongs_to_many :keywords
validates :title, presence: true
validates :body, presence: true
accepts_nested_attributes_for :keywords
# validates :keywords, presence: true
end现在,我只注释掉了Post模型中的关键字。我不太确定是否需要删除它。我已经有了一些现有的帖子,我不想因为这次转换而失去这些帖子,所以我试着在弄清楚如何让这个帖子生效的时候把它放在心上。我真正感到困惑的是我需要在控制器中更改什么。
这是我的Post控制器:
require 'pry'
class Api::V1::PostController < ApiController
before_action :authorize_user, except: [:index, :show]
# INDEX /post
def index
render json: Post.all, each_serializer: PostSerializer
end
# SHOW /post/1
def show
render json: Post.find(params[:id]), serializer: PostShowSerializer
end
# CREATE /post/new
def create
binding.pry
post = Post.new(post_params)
post.user = current_user
if post.save
render json: post
else
render json: { errors: post.errors.full_messages }
end
end
# UPDATE /post/update
def update
post = Post.find(params[:id])
if post.update(post_params)
render json: post
else
render json: { errors: post.errors.full_messages }
end
end
# DESTROY /post/destroy
def destroy
post = Post.find(params[:id])
if post.destroy
render json: {destroyed: true}
end
end
protected
def post_params
params.require(:post).permit([:title, :body, :image, :keywords])
end
def authorize_user
if !user_signed_in? || current_user.role != "admin"
redirect_to root_path
end
end
end在上面的状态中,当我到达这个部分post = Post.new(post_params)时,我得到一个错误,说是NoMethodError (undefined method 'each' for "authorlife":String)。如果从post_params中删除keywords,则会出现以下错误Unpermitted parameter: :keywords
我觉得我在这里遗漏了一个或多个步骤,但我已经有一段时间没有做过像这样的关联表了。
更新:遵循下面的一些建议,我更新了上面的代码,使其看起来像现在的样子。当前的问题是,当我在#create方法中检查post_parms时,我根本不再接收到关键字。我检查了前台,它正在发送关键字。我假设是我的post_params导致了这个问题。我尝试过像这样添加关键字嵌套属性,但是关键字仍然没有显示在post_params中
def post_params
params.require(:post).permit(:title, :body, :image, :keywords_attributes => [:id, :keyword])
end这是我试图实现的代码的WIP。一旦我弄清楚了参数的情况,我不确定关键字部分应该是什么样子。
params = { post: {title: post_params["title"], body: post_params["body"], image: post_params["image"], keywords_attributes: [{ keyword: 'keyword title' },]
}}发布于 2021-08-27 01:13:37
在上面的状态中,当我到达这个部分
= Post.new(post_params)时,我得到一个错误,说NoMethodError (未定义的方法‘’for "authorlife":String)。如果我从post_params中删除关键字,我会得到这个错误::关键字参数不允许
如果要通过post更新关键字,则需要设置关键字的嵌套属性。
class Post < ApplicationRecord
belongs_to :user
has_and_belongs_to_many :keywords
validates :title, presence: true
validates :body, presence: true
accepts_nested_attributes_for :keywords
end然后,您可以在您的控制器中传入这样结构的params
params = { post: {
title: 'title', body: "body", keywords_attributes: [
{ text: 'keyword title' },
]
}}
post = Post.create(params[:post])https://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html
我已经有了一些现有的帖子,我不想因为这次转换而失去这些帖子,所以我正在努力保持这一点,因为我想知道如何让它发挥作用。
删除不再使用的数据是一种很好的做法。您应该编写一个数据迁移,将现有的关键字从posts表移动到keywords表。像这样的东西
class KeywordsMigrator
def run
Post.all.each do |post|
keyword = Keyword.find_or_create_by(title: post.keyword)
post.keywords << keyword
end
end
end最后,您可以从post中删除keyword列。
您并没有真正提到posts表的当前结构,所以我假设您在那里有一个keyword列。如果您有一个keywords列,那么您必须对您的关联进行不同的命名,直到您删除该列为止,否则您将遇到麻烦。例如,将其重命名为keywords_v1并指定class_name。
class Post < ApplicationRecord
belongs_to :user
has_and_belongs_to_many :keywords_v1, class_name: "Keyword"
validates :title, presence: true
validates :body, presence: true
end或者先将该列重命名为类似于deprecated_keywords的名称。
https://stackoverflow.com/questions/68946768
复制相似问题