如何在Rails中通过JSON请求批量保存多表数据?求示例
Hey there! Let's walk through how to build this batch creation feature for your Rails app. Your request needs to create both a Post and multiple Comments in one JSON POST, so we'll make sure this works safely (if any part fails, nothing gets saved) and follows Rails best practices.
Step 1: Ensure Your Models Are Set Up
First, confirm you have a Post model (if not, generate it with these commands):
rails generate model Post title:string body:text rails db:migrate
Then update your models to add associations (critical for linking comments to the post):
# app/models/post.rb class Post < ApplicationRecord has_many :comments, dependent: :destroy end # app/models/comment.rb class Comment < ApplicationRecord belongs_to :post end
Step 2: Create a Batch Creation Controller
We'll make a dedicated controller to handle this non-standard batch action (keeps your existing CommentsController clean). Create app/controllers/batch_creations_controller.rb:
class BatchCreationsController < ApplicationController # POST /batch_create def create # Use a transaction to guarantee atomicity: all records save, or none do ActiveRecord::Base.transaction do # Create the parent Post first @post = Post.new(post_params) unless @post.save render json: { errors: @post.errors.full_messages }, status: :unprocessable_entity raise ActiveRecord::Rollback # Trigger full rollback if post fails end # Create each Comment linked to the new Post @comments = params[:comment].map do |comment_data| comment = @post.comments.new(comment_params(comment_data)) unless comment.save render json: { errors: comment.errors.full_messages }, status: :unprocessable_entity raise ActiveRecord::Rollback # Rollback if any comment fails end comment end end # If we reach here, everything saved successfully render json: { post: @post, comments: @comments }, status: :created end private def post_params params.require(:post).permit(:title, :body) end def comment_params(comment_data) comment_data.permit(:title, :body) end end
Step 3: Add the Route
Update config/routes.rb to map the batch POST endpoint:
Rails.application.routes.draw do # ... your existing routes ... post '/batch_create', to: 'batch_creations#create' end
Step 4: Test the Request
You can test this with curl (replace localhost:3000 with your app's URL if needed):
curl -X POST http://localhost:3000/batch_create \ -H "Content-Type: application/json" \ -d '{ "post": { "title":"Titlea 2", "body":"body of the post 2" }, "comment":[ { "title":"Comment 1", "body":"First comment body" }, { "title":"Comment 2", "body":"Second comment body" } ] }'
Quick Fix for Your Existing CommentsController
I noticed a small typo in your current comment_params method—you're permitting a :comment parameter, but your model (and request example) uses :body. Update it to:
def comment_params params.require(:comment).permit(:title, :body) end
内容的提问来源于stack exchange,提问作者Javier Joasimar Palos Flores

