I have a model entities with a HMT relationship in the model user_entity_roles. I create new entities with a nested form. In the controller, this is a 2 step process via the new and create methods. I can't figure out how to write a test for creating a new entity.
Models:
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 Controller:
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
Entities Test Controller:
test 'should create entity with valid params' do
sign_in_as @user
assert_difference -> { Entity.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: 0, # This is wrong
user_id: @user.id,
is_manager: 1,
is_editor: 1
}
}
}
end
end
This doesn't work, because the entity_id in the nested user_entity_role must be the id of the newly created entity.
Edit: Per the first answer, this is also in the controller. Maybe the error is there?
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
What I don't get here is why the user_entity_role is being created from user input at all and not just being created in the controller.
Surely it's not up to the user to decide the authorization logic for newly created items in your application?
def new
@entity = Entity.new
end
def create
@entity = Entity.new(entity_params)
@entity.user_entity_roles.new(
user: Current.user,
is_manager: true,
is_editor: true
)
if @entity.save
redirect_to @entity
else
render :new, status: :unprocessable_entity
end
end
# ...
def entity_params
params.require(:entity) # line breaks are free dude
.permit(
:company, :street, :house_number, # do not include id
:zip, :city, :tax_number,
:vat_id, :hrb,:managing_director,
:iban, :bank, :invoice_number_format_id
)
end
def valid_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
}
}
end
test 'should create entity with valid params' do
sign_in_as @user
assert_difference -> { Entity.count }, 1 do
post entities_url, params: valid_params
end
end
test 'should add role to user' do
assert_difference -> { @user.user_entity_roles.count }, 1 do
post entities_url, params: valid_params
end
end
You should carefully consider what attributes in your model you're actually exposing though your API.
Additionally having boolean attributes prefaced with is_
is in itself an anti-pattern. There are much better ways to this beyond having an ever growing number of boolean columns in the table like for example having a roles
table containing a definition and a user_roles
table that joins roles and users.