Search code examples
ruby-on-railsrubyvalidationrails-activestorage

How to validation depend on different submit buttons


My application has "save_button", "check_button" and "submit_button" and I want to have validation only, if I click "submit_button" to avoid if someone does not attach any files(tape_files) and submit.

Model:
validates :tape_files, attached: true, on: :update
View:
<%= f.submit "Save", name: "save_button" %>
<%= f.submit "Check", name: "check_button" %>
<%= f.submit "Submit", name: "submit_button" %>
def update
    @tape.update(tapes_params)
    if params[:save_button]
      redirect_to tapes_path, notice: "Saved!"
    elsif params[:check_button]
      redirect_to tapes_path, notice: "Checked!"
    elsif params[:submit_button]
        redirect_to tape_file_tape_path(@tape.id), notice: "Attachment Saved!"   
    end

I found that "save(false)" has an ability to skip the validation but I have really no idea how can I integrate it into the validation. Does someone know how the validation should be modified only for "submit_button" validation?


Solution

  • It's hard for me to offer more than a code fix here as I don't understand the entire use case of your code and domain but have you explored the use of a custom context with on?

    Changes you could explore with your code, if I understand you want the validation to run only when the submit_button is clicked. Otherwise I hope you get the idea of how to customize it for your exact needs.

    Model:
    # You can change the context to be a custom one, 
    # or use multiple e.g. on: [:update, :submitted]
    validates :tape_files, attached: true, on: :submitted
    
    
    def update
      # [1] Change to assign_attributes
      @tape.assign_attributes(tapes_params)
    
      if params[:submit_button] 
        # [2] This will run all validations without an explicit
        # context PLUS the `:submitted` ones.
        if @tape.save(context: :submitted)
          redirect_to tape_file_tape_path(@tape.id), notice: "Attachment Saved!"
        else
          render 'edit', notice: "Update failed"
        end
      else
        # [3] This will run all validations without an explicit context.
        if @tape.save
          if params[:save_button]
            redirect_to tapes_path, notice: "Saved!"
          elsif params[:check_button]
            redirect_to tapes_path, notice: "Checked!"
          else
            # [Optional] You may want to consider handling a default redirect here
          end
        else
          render 'edit', notice: "Update failed"
        end
      end
    end