Ruby on Rails嵌套表单创建实体的控制器测试问题
Rails嵌套表单创建实体的测试问题解决
问题场景
在Ruby on Rails项目中,Entity与UserEntityRole通过HMT(Has Many Through)关联,创建新实体时使用嵌套表单,控制器通过new和create分两步实现。但编写创建实体的测试代码时,因嵌套的user_entity_role参数错误导致测试失败——错误传入了id:0,让Rails误以为要更新已有记录,而实际上需要创建新的关联记录,且新实体的ID会由Rails自动关联到user_entity_role。
相关代码
模型代码
class Entity < ApplicationRecord has_many :invoices, dependent: :restrict_with_error has_many :user_entity_roles, dependent: :destroy accepts_nested_attributes_for :user_entity_roles has_many :users, through: :user_entity_roles, dependent: :restrict_with_error belongs_to :invoice_number_format has_many :debitors, dependent: :restrict_with_error validates_associated :user_entity_roles validates :company, presence: true validates :street, presence: true validates :house_number, presence: true validates :zip, presence: true validates :city, presence: true end class UserEntityRole < ApplicationRecord belongs_to :entity, touch: true belongs_to :user validates :entity_id, uniqueness: { scope: :user_id } end
Entities控制器代码
def new @entity = Entity.new @entity.user_entity_roles.build @entity.user_entity_roles.first.user_id = Current.user.id end def create @entity = Entity.new(entity_params) if @entity.save redirect_to @entity else render :new, status: :unprocessable_entity end end
控制器参数方法
def entity_params params.require(:entity).permit( :id, :company, :street, :house_number, :zip, :city, :tax_number, :vat_id, :hrb, :managing_director, :iban, :bank, :invoice_number_format_id, user_entity_roles_attributes: %i[id is_manager is_editor user_id] ) end
修正后的测试代码
问题出在测试参数中给user_entity_roles_attributes传入了id:0,创建新关联记录时不需要指定id,Rails会自动处理新记录的创建并关联到刚生成的Entity。同时可以增加对UserEntityRole计数的验证,让测试更完整:
test 'should create entity with valid params' do sign_in_as @user assert_difference -> { Entity.count }, 1 do assert_difference -> { UserEntityRole.count }, 1 do post entities_url, params: { entity: { company: 'MyString', street: 'MyString', house_number: 'MyString', zip: 'MyString', city: 'MyString', tax_number: 'MyString', vat_id: 'MyString', hrb: 'MyString', invoice_number_format_id: 2, user_entity_roles_attributes: { # 移除错误的id参数 user_id: @user.id, is_manager: 1, is_editor: 1 } } } end end # 验证关联记录的正确性 entity = Entity.last assert_equal @user.id, entity.user_entity_roles.first.user_id assert entity.user_entity_roles.first.is_manager assert entity.user_entity_roles.first.is_editor end
关键说明
- 创建嵌套关联记录时,不要传入
id参数,否则Rails会尝试更新对应ID的记录而非创建新记录。 - 新创建的Entity的ID会由Rails自动赋值给
user_entity_roles的entity_id,无需手动指定。 - 增加对关联模型计数和属性的验证,能确保嵌套关联正确创建。
内容的提问来源于stack exchange,提问作者Ricky883249
相关产品推荐
相关产品推荐

