The problem in testing a create action is that the object is not already created. Thus a class policy initialisation could state:
def initialize(user, promotion)
@user = user
@promotion = promotion
end
with @shop = @promotion.shop_id
added to the edit/update/delete policy actions.
However, the user may have a role within that shop that allows it to do some privileged actions, such as create
...
def shopmanager
@roleshopuser ||= Roleshopuser.where(['user_id = ? AND shop_id = ? AND role_id IN (?)', user.id, @shop, [1,2]]).first
end
note: this functions properly on edit/update/destroy actions, thus validating the testing fixtures
As the initialisation process indicates, the promotion requires a shop_id and is thus a submitted param to the create action. Therefore the controller action is defined as (with the puts confirming the presence of the parameter):
def create
puts params[:promotion][:shop_id]
@target_shop = params[:promotion][:shop_id]
@promotion = Promotion.new(promotion_params)
authorize @promotion
and the policy adapted accordingly
def create?
@shop = @target_shop
puts user.id
puts user.admin?
puts shopmanager.nil?
!user.nil? && (user.admin? || !shopmanager.nil?)
end
again the puts
do indicate that there is proper handling of the attributes and method
The test however fails
test "should create promotion" do
@shop = shops(:three_4)
@shopusers.each do |user|
sign_in user
@shopusers.each do |user|
sign_in user
assert_difference('Promotion.count') do
post promotions_url, params: { promotion: { name: (@promotion.name + user.id.to_s), shop_id: @promotion.shop_id [...]
end
assert_redirected_to promotion_url(Promotion.last)
end
sign_out user
end
end
From the puts
data, the policy runs on user.admin?
, but the policy fails where true
is returned for the next user fixture when running method shopmanager.nil?
(admin is false). As the edit/update functions work with the same fixtures, this points to an error in the policy for create
.
What is it?