Rails 4:提交表单时如何额外插入一条数据行?
Hey there! Let's work through this problem together. You want to generate two invite records every time a user submits your invite form—one for the selected recipient, and an extra one for the user named "Intruder". Here are two clean, Rails-friendly ways to make this happen:
Option 1: Handle it directly in the controller
This approach is straightforward and keeps the logic visible where the form submission is processed. We'll use a database transaction to ensure both invites are created successfully (or neither is, if something goes wrong).
class InvitesController < ApplicationController def create @invite = Invite.new(invite_params) # Wrap everything in a transaction to avoid partial saves ActiveRecord::Base.transaction do if @invite.save # Find the "Intruder" user (adjust the field name if you use username instead of name) intruder = User.find_by(name: "Intruder") if intruder # Create the second invite, reusing the event from the original submission Invite.create!(user_id: intruder.id, event_id: @invite.event_id) else # Handle the case where "Intruder" doesn't exist (log an error or alert the user) raise ActiveRecord::RecordNotFound, "Intruder user not found" end redirect_to invites_path, notice: "Invites sent successfully!" else render :new end rescue ActiveRecord::RecordInvalid, ActiveRecord::RecordNotFound => e redirect_to new_invite_path, alert: "Failed to create invites: #{e.message}" end end private def invite_params params.require(:invite).permit(:user_id, :event_id) # Add any other invite fields here end end
Option 2: Use a model callback
If you want this behavior to apply every time an invite is created (not just via the form), a model callback is a good fit. We'll add an after_create hook to automatically generate the Intruder invite, with a guard clause to avoid infinite loops or duplicates.
class Invite < ApplicationRecord belongs_to :user belongs_to :event # Only trigger the extra invite if the original invite isn't for Intruder themselves after_create :create_intruder_invite, unless: :intruder_invite? private def create_intruder_invite intruder = User.find_by(name: "Intruder") return unless intruder # Skip if an invite for Intruder to this event already exists unless Invite.exists?(user_id: intruder.id, event_id: event_id) Invite.create!(user_id: intruder.id, event_id: event_id) end end def intruder_invite? user.name == "Intruder" end end
Quick Notes to Keep in Mind:
- Ensure the "Intruder" user exists: Add
User.find_or_create_by(name: "Intruder")to yourdb/seeds.rband runrails db:seedto guarantee this user is in your database. - Validation checks: If your
Invitemodel has uniqueness validations (e.g., a user can't be invited to the same event twice), make sure the callback checks for existing invites before creating a new one. - Error handling: Both examples use
create!which raises an exception on failure—this ensures the transaction rolls back if either invite can't be saved.
内容的提问来源于stack exchange,提问作者Tadej Firšt

