Shrine

Model record not fully loaded at Attacher.validate

Hi! First I want to say thanks for this great tool! :slight_smile:

I’ve noticed a strange behavior and I’m not sure if it’s a bug. I want to dynamicly validate uploaded files based on an attribute of the Model. In my tests I use attr_accessor :by_admin and I also tried to store this attibute in the database. The results vary slightly between these two but have the same result. Here comes the code:

class Gallery < ApplicationRecord

  # I use this validation to see how ActiveModel::Validations handle this:
  validates :name, length: { minimum: 5 }, unless: :is_admin

  attr_accessor :by_admin

  include PictureUploader::Attachment(:file)

  private

  def is_admin
    # Existing or new record:
    # self -> #<Gallery:0x00007fcf57877840 id: [1|nil], name: "Test", ...>
    # self.by_admin -> "0" or "1" depending on my test checkbox in the form
    # This is the behavior I would expected in Shrine validations too. But they don't.
    by_admin == '1'
  end
end
class PictureUploader < Shrine
  plugin :determine_mime_type, analyzer: :marcel
  Attacher.validate do
    # New or existing record, by_admin: checked or not checked
    # record -> #<Gallery:0x00007feb53a27628 id: [nil|1], name: "Test", file_data: "{\"id\":\"3ca4e2a220a631d8c0a0147dcdbadf32.svg\",...}", ...>
    # record.by_admin -> nil # always
    # I belive the params are not fully set at this point. :name is but :by_admin not!???
    # With attribute stored in the DB:
    # record.by_admin -> true or false # new records always false (the default). Existing records have the attribute like it is in the DB and not the assigned one through the form params.
    if record.by_admin == '1'
      validate_extension ['jpg','jpeg','svg']
      validate_mime_type ['image/jpeg','image/svg+xml']
    else
      validate_extension ['jpg','jpeg']
      validate_mime_type ['image/jpeg']
    end
  end
end

I also tried to use the context of the Attacher but this has similar behavior:

class Gallery < ApplicationRecord
  ...
  def file=(attachment)
    # This sets the context[:by_admin] but is always false.
    # Looks like the params are also not fully set here.
    file_attacher.context[:by_admin] = is_admin
    super(attachment)
  end
  ...
end

Did I miss something or did somthing wrong? Any suggestions for a soulution would be very appreciated. :slight_smile: Thank you very much!

PS.: I created a demo Rails app for testing which can be found here: https://github.com/factor4/shrine_validation There is also a branch for by_admin_in_db