DRY Validations for Similar Models
In my app I have restaurants which have a name, address, state, zipcode, country, and some other stuff. These restaurants have many locations, and each location belongs to a restaurant. The locations also hold a name, address, state, zipcode, and country. I was wondering if there is a clean way of writing validations in their model files without having to repeat myself in each model file? Can validations go into a function?
Definitely! You can probably do this cleanest by creating a Concern and putting the validations in there, then including the concern in both models. That's exactly the purpose they're designed for, so they should do exactly what you want.
Just to provide an alternative solution - If you're still early in the development cycle and haven't gone to production yet, you could also create a contact model that stores all the address info, then you'd only have one model to manage validations:
#models/restraunt.rb has_one :contact, as: :contactable, dependent: :destroy #models/location.rb has_one :contact, as: :contactable, dependent: :destroy #models/contact.rb belongs_to :contactable, polymorphic: true
then your migration could be something like:
class CreateContacts < ActiveRecord::Migration def change create_table :contacts do |t| t.string :line_1 t.string :line_2 t.string :city t.integer :state, :default => 0 t.string :zip t.string :email t.string :phone t.decimal :lat, :precision => 10, :scale => 6, :default => 0 t.decimal :lng, :precision => 10, :scale => 6, :default => 0 t.references :contactable, polymorphic: true, index: true t.timestamps null: false end end end
In addition, here is the code I used for the solution Chris suggested, for anyone interested.
# /models/concerns/location_validations.rb module LocationValidations extend ActiveSupport::Concern included do validates :name, presence: true validates :address, presence: true validates :state, presence: true validates :zipcode, presence: true validates :country, presence: true end end
# models/restaurant.rb class Restaurant < ApplicationRecord has_many :branches has_and_belongs_to_many :users validates :phone, presence: true validates :email, presence: true include LocationValidations end
# models/branch.rb class Branch < ApplicationRecord belongs_to :restaurant validates :restaurant_id, presence: true include LocationValidations end