Home > Software engineering >  Rails routing bug in "redirect_to" and "notice" flash message
Rails routing bug in "redirect_to" and "notice" flash message

Time:11-26

I need to show notice/pop ups upon hitting of a button. Similar approaches are working in other views and controllers of the app but here on this Import button things are not working since long. None of the redirect_to works in the controller while their similar usage in other controller works.

routes.rb:

Rails.application.routes.draw do
  namespace :admin do
    get '', to: 'dashboard#index', as: 'root'
    # resourceful routes 
    resources :oauth_clients
    resources :tenants do
      resources :sites do
        #resources :production_shifts
        resources :units do
          resources :log_data_fields, only: [:import, :create, :index, :destroy, :download_csv] do 
            get :download_csv
            # collection route 
            collection do 
              post :import #post action 
            end
          end

log_data_fields_controller.rb:

class Admin::LogDataFieldsController < Admin::BaseController
  require 'csv'

  # import request(this is gonna be a POST action)
  def import
    logger.debug("*****Testing the logger.*****")
    
    file = params[:log_data_field][:file]
    
    # return redirect_to [:admin, @tenant, @site, @unit], notice: "Only CSV please !!" unless file.content_type == "text/csv"  
    return redirect_to admin_tenant_site_unit_log_data_fields_url, notice: "Only CSV please !!" unless file.content_type == "text/csv"  
    
    file = File.open(file)
    csv = CSV.parse(file, headers: true) 
    # csv = CSV.parse(file, headers: true, col_sep: ";") 
    
    @unit = Unit.find_by_id(params[:unit_id])
    # p @unit.id 
    
    total_rows = CSV.read(file).count
    count = 1
    # binding.b

    csv.each do |row|
      tag_hash = {}
      tag_hash[:name] = row["Name"]
      tag_hash[:alias] = row["Alias"]
      tag_hash[:column_type] = row["Type"]
      tag_hash[:unit_id] = @unit.id
      tag_hash[:is_active] = row["Active"]
      # binding.b
      # p row
      logger.debug("           Mapping              ")
      @log_data_field = LogDataField.create(tag_hash)
      # binding.b
      if @log_data_field.save
        count  = 1
        logger.debug("--------Saves--------")
        # return redirect_to admin_tenant_site_unit_log_data_fields_path(@tenant, @site, @unit), 
      else
        # return redirect_to admin_tenant_site_unit_log_data_fields_path(@tenant, @site, @unit), 
        # render :_importtags 
      end  
    end
    
    logger.debug("-------------Going down----------")
    
    if count == total_rows && count > 1
      logger.debug("-------------All succeeded----------")
      redirect_to admin_tenant_site_unit_log_data_fields_path(@tenant, @site, @unit), flash: { :notice => "Success"}
      # flash.notice = "Success : Tags imported from CSV !"
    elsif total_rows == 0
      logger.debug("-------------All zero----------")
      flash.alert = "Import Failure : CSV cant be empty"
      render :action => 'index', :notice => "Import Failure : CSV cant be empty."
    else
      logger.debug("-------------Failed down----------")
      flash.alert = "Import Failure"
      render :action => 'index', :notice => "Import Failure"
    end

    redirect_to import_admin_tenant_site_unit_log_data_fields_url(@tenant, @site, @unit), notice:"Imported tags !"
  end

_importtags.html.haml:

%p{:style => "color: green"}= notice

= form_with model:@log_data_field, url: import_admin_tenant_site_unit_log_data_fields_path, method: :post do |form|

    - if @log_data_field.errors.any?
        #error_explanation
            %h2= "#{pluralize(@log_data_field.errors.count, "error")} prohibited this log_data_field from being saved:"
            %ul
            - @log_data_field.errors.full_messages.each do |message|
                %li= message

    -# = link_to 'Download sample csv', [:admin, @tenant, @site, @unit, @log_data_field], method: :get

    = form.file_field :file, accept: ".csv"
    -# = form.file_field :file
    <br>
    <br>

    -#button.btn.primary{:type => "submit", data: { disable_with: "Please wait..."}}
    %button.btn.primary{:type => "submit"}
        = "Import"

Comments are the things I have tried.

Sorry if you find the question or its structure very unprofessional but I am beginner and learning regularly. I need to render the view again upon hitting that Import button to show either any errors if availabe or success on importing tags from csv. There is also issue of notice not being visible or popping up and redirect_to not working when non-csv document is submitted in the form which should give a warning too but it is not coming.

I believe the solution will be very short or some typo or silly mistake in understanding the path vs url routes.

EDIT As per @markets suggestion I made all the redirect_to with return which are used in between so the notice are working but they appear only on refresh. Still can't get them instantly on button click:

class Admin::LogDataFieldsController < Admin::BaseController
  before_action :set_tenant
  before_action :set_site
  before_action :set_unit

  require 'csv'

  # import request(this is gonna be a POST action)
  def import
    logger.debug("*****Testing the logger.*****")
    
    file = params[:log_data_field][:file]
    
    # return redirect_to [:admin, @tenant, @site, @unit], notice: "Only CSV please !!" unless file.content_type == "text/csv"  
    return redirect_to admin_tenant_site_unit_log_data_fields_path(@tenant, @site, @unit), notice: "Only CSV please !!" unless file.content_type == "text/csv"  

    file = File.open(file)
    csv = CSV.parse(file, headers: true) 
    # csv = CSV.parse(file, headers: true, col_sep: ";") 
    
    @unit = Unit.find_by_id(params[:unit_id])
    # p @unit.id 
    
    total_rows = CSV.read(file).count
    count = 1
    # binding.b

    csv.each do |row|
      tag_hash = {}
      tag_hash[:name] = row["Name"]
      tag_hash[:alias] = row["Alias"]
      tag_hash[:column_type] = row["Type"]
      tag_hash[:unit_id] = @unit.id
      tag_hash[:is_active] = row["Active"]
      # binding.b
      # p row
      logger.debug("           Mapping              ")
      @log_data_field = LogDataField.create(tag_hash)
      # binding.b
      if @log_data_field.save
        count  = 1
        logger.debug("--------Saves--------")
        # return redirect_to admin_tenant_site_unit_log_data_fields_path(@tenant, @site, @unit), 
      # else
        # return redirect_to admin_tenant_site_unit_log_data_fields_path(@tenant, @site, @unit), 
        # render :_importtags 
      end  
    end
    
    logger.debug("-------------Going down----------")
    
    if count == total_rows && count > 1
      logger.debug("-------------All succeeded----------")
      return redirect_to admin_tenant_site_unit_log_data_fields_path(@tenant, @site, @unit), flash: { :notice => "Success : Tags imported from CSV !"}
    elsif total_rows == 0
      logger.debug("-------------All zero----------")
      return redirect_to admin_tenant_site_unit_log_data_fields_path(@tenant, @site, @unit), flash: { :notice => "Import Failure : CSV cant be empty"}
    else
      logger.debug("-------------Failed down----------")
      return redirect_to admin_tenant_site_unit_log_data_fields_path(@tenant, @site, @unit), flash: { :notice => "Import Failure : PLease check CSV"}
    end

    redirect_to import_admin_tenant_site_unit_log_data_fields_url(@tenant, @site, @unit), notice:"Imported tags !"
  end

CodePudding user response:

If you are calling render or redirect_to in the middle of a controller (not the last line), you should use return too in order to stop the current execution path:

return redirect_to(...)

or

redirect_to(...) and return

More info: https://api.rubyonrails.org/v7.0.4/classes/ActionController/Redirecting.html

  • Related