dry-rb / dry-rails

The official dry-rb railtie
https://dry-rb.org/gems/dry-rails
MIT License
270 stars 27 forks source link

Integration between AM:V and dry-schema #27

Closed gotar closed 4 years ago

gotar commented 4 years ago

I made something like this to automatically import dry-schema (contract) from my Custom class to a Rails model, so every tool (gem) that require model validation automatically use schema

class Vehicle < ApplicationRecord
  validates_with CustomValidator, type: :vehicle
end

class CustomValidator < ActiveModel::Validator
  include Namespace::Import[
    vehicle_contract: 'vehicles.contracts.new',
  ]

  def validate(record)
    validator = case options[:type]
                when :vehicle then vehicle_contract.(record.attributes)
                end

    unless validator.success?
      validator.errors.to_h.each do |key, errors|
        errors.each do |error|
          record.errors[key] << error
        end
      end
    end
  end
end

>> v = Vehicle.new
>> v.valid?
=> false
>> v.errors
=> #<ActiveModel::Errors:0x000055bae1ce8500 @base=#<Vehicle id: nil, company_id: nil, vin: nil, created_at: nil, updated_at: nil, deleted_at: nil, leaser: nil, leasing_end: nil, bik: nil, cost: nil, plate: nil, data: nil, rental_price: nil, vehicle_category_id: nil, retribution_price: nil, gearbox: "auto", vehicle_brand_id: nil, engine: "Petrol", fuel: "Petrol">, @messages={:company=>["must exist"], :vehicle_category=>["must exist"], :vehicle_brand=>["must exist"], :company_id=>["must be filled"], :vehicle_category_id=>["must be filled"], :vehicle_brand_id=>["must be filled"], :vin=>["must be filled"], :plate=>["must be filled"], :leaser=>["must be filled"], :leasing_end=>["must be filled"], :bik=>["must be filled"], :cost=>["must be filled"], :rental_price=>["must be filled"], :retribution_price=>["must be filled"]}, @details={:company=>[{:error=>:blank}], :vehicle_category=>[{:error=>:blank}], :vehicle_brand=>[{:error=>:blank}]}>>>

Works like a charm, so maybe will be useful for someone, plus I think It's quire easy to add to dry-rails itself.

solnic commented 4 years ago

Thanks for sharing this. I can see how this could be handy but the plan is actually to have "form objects" rather than using AR validation.

In the future please start a thread on our forum with a feature proposal rather than reporting an issue. We use issues for bug reports and approved feature requests only.

gotar commented 4 years ago

@solnic it’s useful in many cases so adding this to maybe a documentation will save a lot of people time.

solnic commented 4 years ago

@gotar it's not in line with the concept of validating data before passing to models, because of this it cannot be even documented, despite being handy in some cases. I'm not saying it's inherently wrong to handle validation like that, we just shouldn't document how to do something that doesn't follow architectural patterns we've been promoting for few years now.