简体   繁体   中英

Rails single table inheritance validation

There is a Request model in my app. On different pages I need different validations, for example on /contacts I need to validate a lot of fields, whereas in a 'call me back later' popup I need to validate only phone number and name.

My problem is: data is saved, but without validations and type is not saved aswell.

Structure: request.rb

class Request < ApplicationRecord

  self.inheritance_column = :_type_disabled

  def self.types
      %w(ContactRequest CallMeBackRequest)
  end

  scope :contacts, -> { where(type: 'ContactRequest') } 
  scope :callmebacks, -> { where(type: 'CallMeBackRequest') } 
end

routes.rb:

resources :contact_requests, only: [:new, :create], controller: 'requests', type: 'ContactRequest'
resources :call_me_back_requests, only: [:new, :create], controller: 'requests', type: 'CallMeBackRequest'

contact_request.rb:

class ContactRequest < Request
  validates :name, :phone, :email, :company_name, presence: true

  def self.sti_name
    "ContactRequest"
  end
end

call_me_back_request.rb:

class CallMeBackRequest < Request
  validates :name, :phone, presence: true

  def self.sti_name
    "CallMeBack"
  end
end

requests_controller.rb:

class Front::RequestsController < FrontController
  before_action :set_type

  def create
    @request = Request.new(request_params)

    respond_to do |format|
      if @request.save
        format.js
      else
        format.js { render partial: 'fail' }

      end
    end
  end

  private

  def set_request
    @request = type_class.find(params[:id])
  end

  def set_type
     @type = type
  end

  def type
      Request.types.include?(params[:type]) ? params[:type] : "Request"
  end

  def type_class 
      type.constantize 
  end

  def request_params
    params.require(type.underscore.to_sym).permit(Request.attribute_names.map(&:to_sym))
  end
end

My form starts with:

=form_for Request.contacts.new, format: 'js', html: {class: 'g-contact__sidebar-right g-form'}, remote: true do |f|

I tried using ContactRequest.new - result was the same.

What I get when I hit the console:

  • Request.contacts.create!(name: "something") - does get saved, no validations are applied (why?). No type field is populated - why?
  • ContactRequest.create!(name: "something") - does not get saved, validations are applied
  • ContactRequest.create!(name: ..., all other required fields) - does get saved, but field type is empty - why?

Whatever I use for my form - ContactRequest.new or Request.contacts.new - neither validations are applied nor field type is set correctly.

Can anyone point me in the right direction? I'm mainly using this tutorial and other SO question, but without success.

Figured it out - since I'm not using the dedicated pages and paths for those contacts, ie contact_requests_path and corresponding new.html.haml , I need to pass the type parameter as a hidden field.

So my form now looks like this:

=form_for ContactRequest.new, format: 'js', html: {class: 'g-contact__sidebar-right g-form'}, remote: true do |f|
  =f.hidden_field :type, value: "ContactRequest"

Considering validations - I don't know what I did, but after restarting the server a few times, they work now. The only this I remember really changing was the sti name here:

class CallMeBackRequest < Request
  validates :name, :phone, presence: true

  def self.sti_name
    "CallMeBack" <- changed it from "CallMeBack" to "CallMeBackRequest"
  end
end

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM