Reputation: 111
There are mulitple controller actions that receive startDate as a parameter and pass it on to relevant models to fetch the data. Based on a user property, there are validation rules that has to be applied on this parameter. Validation wouldn't just fail, but instead assigns a default value specific to that user property.
The modification required on startDate is common across all the actions and should be applied in all the cases. So, i assume this logic shouldn't be repeated at each model. Instead, controller's before_action filter, something like filtered_params sounds the right place to do it.
before_action :filtered_params
def filtered_params
params.require(:query).permit(:start_date)
user = User.instance
if(user.type == 'student') {} # startDate should be Greater than or equal to 12-03-2018. modify params.startDate with the logic
elsif(user.type == 'professor') {} // startDate should be Greater than equal to 01-01-2018
else {} // do nothing
end
end
The above approach works, but i do not want to get stuck in if else loop. Is there a better way to do it ?
Upvotes: 0
Views: 327
Reputation: 20263
Perhaps you could do something like:
before_action :filtered_params
def filtered_params
@filtered_params ||= get_filtered_params
end
def get_filtered_params
# not sure about this user assignment, but let's go with it...
user = User.instance
begin
"ParamsFilter::#{user.type.camelize}Service".constantize.call params
rescue NameError => e
# I'm guessing at the default behavior here. You would need to
# modify to meet your requirements.
return params.require(:query).permit(:start_date)
end
end
Then you would need something like:
app
|- services
| |- params_filter
| | |- service_base.rb
| | |- student_service.rb
| | |- professor_service.rb
| |- service_base.rb
And a service might look something like
class ParamsFilter::StudentService < ParamsFilter::ServiceBase
MIN_START_DATE = '12-03-2018'
#======================================================================
# Instance Methods
#======================================================================
def call
# In this case, given how ServiceBase is defined, the params will
# be received as `args`, so you'll need to work with the `args`
# variable, which will contain `params`.
# You could do stuff unique to `student`:
student_stuff
# and then do some common stuff by calling `super`.
super
end
private
def student_stuff
end
end
Where ParamsFilter::ServiceBase
might look something like:
class ParamsFilter::ServiceBase < ServiceBase
#======================================================================
# Instance Methods
#======================================================================
def call
args[:start_date] = self.class::MIN_START_DATE unless start_date_okay?
end
private
def start_date_okay?
args[:start_date] >= self.class::MIN_START_DATE
end
end
Where service_base.rb
might look something like:
class ServiceBase
attr_accessor *%w(
args
).freeze
class << self
def call(args=nil)
new(args).call
end
end # Class Methods
#======================================================================
# Instance Methods
#======================================================================
def initialize(args)
@args = args
end
end
Upvotes: 3
Reputation: 190
As Dave notes, this is odd behavior. However, if you must alter the start_date, consider using a before_validation callback. It's much safer/cleaner NOT to alter the incoming params, but do it at the model level.
class User
MINIMUM_STUDENT_START_DATE = '12-03-2018'
MINIMUM_PROFESSOR_START_DATE = '01-01-2018'
before_validation :set_start_date
def set_start_date
if type == 'student' && start_date < MINIMUM_STUDENT_START_DATE
self.start_date = MINIMUM_STUDENT_START_DATE
elsif type == 'professor' && start_date < MINIMUM_PROFESSOR_START_DATE
self.start_date = MINIMUM_PROFESSOR_START_DATE
end
end
Upvotes: 0