Rails Form Pattern With Delegated Validations

Where do you put validations when you implement the Form pattern in Rails: - all in the model? - all in the form? - both in the model and form? This is a bad idea because you have to keep both model and form validations in sync. This example defines all validations in the model, i.e. validation errors and form helpers work without additional code. ```ruby # # Form object wrapper for all models created when creating a new event. # class CreateEventForm # Rails 4+ include ActiveModel::Model # Rails 3 #extend ActiveModel::Naming #include ActiveModel::Conversion #include ActiveModel::Validations attr_accessor :event, :calendar delegate :id, :persisted?, to: :event def initialize(attributes = {}) @event = Event.new @calendar = Calendar.new attributes.each do |key, value| public_send("#{key}=", value) end setup_associations end # # Save the event and all related models. # def save if valid? ActiveRecord::Base.transaction do event.save! calendar.save! end else false end end def self.model_name Event.model_name end def event_attributes=(attributes) event.attributes = attributes end def calendar_attributes=(attributes) calendar.attributes = attributes end def valid? valid = super # errors.base(:validation_error) unless valid_children? valid && valid_children? end private def valid_children? [ event, calendar ].map(&:valid?).all? { |valid| valid == true } end def setup_associations calendar.event = event end end ``` View example: ```ruby <%= simple_form_for @form do |f| # @form = CreateEventForm.new %> ... f.simple_fields_for :calendar do |calendar| end f.simple_fields_for :event do |event| end ... <% end %> ``` Note, instead of form objects you can always use accepts\_nested\_attributes\_for. However, why should the view define what the model should look like? accepts\_nested\_attributes\_for is a similar hack as the deprecated attr\_accessible.