Reputation: 1810
I have an instance where I will do certain validations on a resource but not another, where the two resources map to the same model.
In concrete, I have an export model which is linked to a competition and I build an export of all the users in that competition. So naturally there will be a validation to ensure that there is a competition attached. However, a client wants to also be able to build all of the user exports at a given time and have it work like the competition exports.
I plan on using two separate resources for that(routes, controllers) but a validation only makes sense on a per resource level.
Anyone have any thoughts wrt best practices?
Upvotes: 1
Views: 1358
Reputation: 814
To be honest, no. Your best solution would be to split responsibility of export variant into specific classes that carry out the behavior you want on a model. Psuedo code for example, just guessing at implementation here- and may need fettling:
class CompetitionExports
self.abstract_class: true # order just include the relevent ActiveRecord modules
MODEL = Export
def initialize(id)
@competition_export_id = id
end
def all
return [] unless validate
MODEL.where(id: competition_exports_id).joins(:users) #can pluck/ select what you want here
end
private
attr_reader :competition_export_id
def validate
return true if MODEL.where(id: competiton_export_id).has_competition?
self.errors.add(:competition, 'does not exist')
false
end
end
class UserExports
self.abstract_class: true # order just include the relevent ActiveRecord modules
MODEL = Export
def initialize(id)
@user_export_id = id
end
def all_at(date)
return [] unless validate(date)
MODEL.where(id: user_exports_id).joins(:users) #can pluck/ select what you want here
end
private
attr_reader :user_export_id
def validate(date)
return true if MODEL.where(id: user_export_id, date: date).present?
self.errors.add(:user, "no users at #{date}")
false
end
end
So here, I have two resources that check the Export model for their own specific behavior, without actually interfering with the model itself. This keeps the business logic at the model level itself, without mixing it in with everything.
In the controller, you could then just instantiate the class you need at the time. So for all Competition users:
export = CompetitionExports.new(params[:id])
export.all
or users at specific date
export = UserExports.new(params[:id])
export.all_at(params[:date])
Both will run through their specific validations before processing the results.
Upvotes: 1
Reputation: 2659
You can set custom validation or conditional validation in rails.
Refer below link
http://www.justinweiss.com/articles/a-lightweight-way-to-handle-different-validation-situations/
Hope it's help you.
Upvotes: 0