Как передать ошибки проверки модели в представление, основанное на другой модели в Rails? - PullRequest
0 голосов
/ 25 мая 2020

Я создал страницу импорта данных, чтобы централизовать эту функцию и удалить множество контроллеров импорта.

У меня есть объект DataImport для получения параметров для контроллера DataImports. Контроллер определяет требуемую модель импорта и запускает сценарий импорта. В случае успеха он отображает индекс импортированных объектов, если нет, он возвращается в форму импорта данных.

Как видите, в случае сбоя проверки, метод save из модель organisation_import.rb возвращает список сообщений об ошибках. Как передать этот список ошибок в экземпляр @data_import, чтобы при обратном рендеринге нового представления отображались ошибки?

Спасибо за вашу помощь!

Модель : data_import.rb

class DataImport
  include ActiveModel::Model
  extend ActiveModel::Naming
  include ActiveModel::Conversion
  include ActiveModel::Validations

  attr_accessor  :file, :playground_id, :object_type_id

  def initialize(attributes = {})
    attributes.each { |name, value| send("#{name}=", value) }
  end

  def persisted?
    false
  end

end

Просмотр: новое. html .erb

<% provide(:title, (t('DataImport'))) %>

<% provide :page_heading do %>
    <%= t('DataImport') %>
<% end %>

  <%= render partial: "shared/error_list", locals: { errors: @data_import.errors } %>

<div class="row mat-form-row">
  <div class="col-md-12"> <h3><%= t('DataImport') %></h3>
  </div>
</div>

<%= form_for @data_import, html: {id: "input_form"}  do |f| %>

  <div class="row mat-form-row">
    <div class="mat-form-field col-md-3">
      <%= f.label :object_type, t('ObjectType'), class: "mat-form-field-label" %>
      <%= f.collection_select :object_type_id, qdm_object_types('import'), :id, :name, {}, { class: "mat-input-element" } %>
    </div>
  </div>

  <div class="row mat-form-row">
    <div class="mat-form-field col-md-3">
      <%= f.label :file, t('SourceFile'), class: "mat-form-field-label" %>
      <%= f.file_field :file, class: "mat-input-element" %>
    </div>
  </div>
  <br/>

  <div class="row">
    <div class="mat-form-field col-md-3">
      <%= f.label :playground, t('Playground'),  class: "mat-form-field-label" %>
      <%= f.collection_select :playground_id, list_of_playgrounds, :id, :translation, {}, { class: "mat-input-element" } %>
    </div>
  </div>

  <div class="mat-button-group">
    <%= link_to t('Cancel'), root_path, method: :get, class: "mat-stroked-button mat-button-base"  %>
    <%= submit_tag(t('Submit'), :onclick => "submitform();", class: "mat-flat-button mat-button-base mat-primary" ) %>
  </div>
<% end %>

Контроллер: data_imports_controller. rb

class DataImportsController < ApplicationController
  # Check for active session
  before_action :authenticate_user!

  def new
    @data_import = DataImport.new
  end

  def create
    @data_import = DataImport.new(params[:data_import])
    if @data_import.file.nil?
      render :new, notice: t('FileNameCannotBeEmpty')
    end
    objects = Parameter.find(@data_import.object_type_id).name.downcase.pluralize
    objects_import = "#{objects}Import".classify.constantize
    @imported = objects_import.new(file: @data_import.file, playground: @data_import.playground_id)

    if @imported.save
      redirect_to "/#{objects}", notice: t('ImportedObjects')
    else
      render :new
    end
  end

end

Пример organisations_import.rb модель:

class OrganisationsImport
  include ActiveModel::Model
  extend ActiveModel::Naming
  include ActiveModel::Conversion
  include ActiveModel::Validations

  attr_accessor :file, :playground

  def initialize(attributes = {})
    attributes.each { |name, value| send("#{name}=", value) }
  end

  def persisted?
    false
  end

  def save
    if imported_organisations.map(&:valid?).all?
      imported_organisations.each(&:save!)
      true
    else
      imported_organisations.each_with_index do |column, index|
        column.errors.full_messages.each do |message|
          errors.add :base, "Row #{index+2}: #{message}"
        end
      end
      false
    end
  end

  def imported_organisations
    @imported_organisations ||= load_imported_organisations
  end

  def load_imported_organisations
    spreadsheet = self.open_spreadsheet(file)
    spreadsheet.default_sheet = 'Organisations'
    header = spreadsheet.row(1)
    (2..spreadsheet.last_row).map do |i|
      record = Organisation.new
      record.playground_id = $Unicity ? 0 : playground # If only one tenant, then the organisations belong to Governance
      record.code = spreadsheet.cell(i,1).to_s
      record.name = spreadsheet.cell(i,6)
      record.parent_code = spreadsheet.cell(i,2).to_s # before_save action sets the parent_id
      record.organisation_level = spreadsheet.cell(i,3) # overwriten by the before_save action
      record.created_by = 'admin'
      record.updated_by = 'admin'
      record.owner_id = 1 # Administrator
      record.status_id = Parameter.find_by_name("New").id if Parameter.exists?(:name => ("New"))

      # Add description translations
      next_cell = 6
      ApplicationController.helpers.list_of_languages.order(:property).each do |translation|
        record.description_translations.build(field_name: 'name', language: translation.property, translation: spreadsheet.cell(i,next_cell))
        next_cell += 1
        record.description_translations.build(field_name: 'description', language: translation.property, translation: spreadsheet.cell(i,next_cell))
        next_cell += 1
      end
      puts "####################### test ####################################"
      puts record.attributes

      record
    end
  end

  def open_spreadsheet(file)
    case File.extname(file.original_filename)
    when ".csv" then Roo::CSV.new(file.path, csv_options: {col_sep: ";"})
#    when ".xls" then Roo::Excel.new(file.path, nil, :ignore)
    when ".xlsx" then Roo::Excelx.new(file.path)
    else raise "Unknown file type: #{file.original_filename}"
    end
  end
end

1 Ответ

0 голосов
/ 26 мая 2020

Вы можете добавлять сообщения об ошибках к ошибкам вашего @data_import объекта.

@imported.errors.full_messages.each{|msg| @data_import.errors[:base] << msg}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...