Rails form validation is designed to go in the model most easily. But I need to make sure the current user has the required privileges to submit a post and the current_user
variable is only accessible in the controller and view.
I found this answer in a similar question:
You could define a
:user_gold
virtual attribute forBook
, set it in the controller where you have access tocurrent_user
and then incorporate that into yourBook
validation.`
How can I set this up with my post and user controller so that the current_user
variable is accessible in the model?
This whole thing is wrong from an application design perspective as @Deefour's answer pointed out. I changed it so my view doesn't render the form unless the condition is true.
The "similar question" is saying you can do something like this
class YourModel < ActiveRecord::Base
attr_accessor :current_user
# ...
end
and then in your controller action you can do something like
@your_model = YourModel.find(params[:id])
@your_model.current_user = current_user
@your_model.assign_attributes(params[:your_model])
if @your_model.valid?
# ...
You can then use self.current_user
within YourModel
's validation methods.
Note I don't think this is what you should be doing though, as I don't consider this "validation" as much as "authorization". An unauthorized user shouldn't even be able to get the part of your action where such an update to a YourModel
instance could be saved.
As for doing the authorization with Pundit as requested, you'd have a file in app/policies/your_model.rb
class YourModelPolicy < Struct.new(:user, :your_model)
def update?
user.some_privilege == true # change this to suit your needs, checking the "required privileges" you mention
end
end
Include Pundit in your ApplicationController
class ApplicationController < ActionController::Base
include Pundit
# ...
end
Then, in your controller action you can do simply
def update
@your_model = YourModel.find(params[:id])
authorize @your_model
# ...
The authorize
method will call YourModelPolicy
's update?
method (it calls the method matching your action + ?
by default) and if a falsy value is returned a 403 error will result.