如何在Rails 4中将属性导出为CSV时格式化属性

时间:2016-10-13 13:21:55

标签: ruby-on-rails csv

我正在尝试将某些记录导出为CSV,因此在我的控制器中我有以下内容:

...
send_data @orders.to_csv, filename: "orders-#{Date.today}.csv"
...

在模型中我有以下内容:

     def self.to_csv

        attributes = %w{ customer_name created_at order_id currency discount subtotal_tax total }

        CSV.generate(headers: true) do |csv|
          csv << attributes
          all.each do |order|
            if order['created_at']
              order['created_at'] = order['created_at'].strftime("%d/%m/%Y")
            end
            csv << attributes.map{ |attr| order.send(attr) }
          end
        end

      end

我想格式化一些参数,你可以从这段代码中看到:

if order['created_at']
  order['created_at'] = order['created_at'].strftime("%d/%m/%Y")
end

所以我有时间格式化我想要的,但这不起作用。

任何想法为什么?

编辑:我的Gemfile

source 'https://rubygems.org'
    ruby '2.2.2'

    gem 'rails', '4.2.1'
    gem 'sass-rails', '~> 5.0'
    gem 'sprockets', '3.1.0'
    gem 'devise'
    gem 'angular-rails-templates'
    gem 'mongoid', '~>4'
    gem 'bson_ext'
    gem "mongoid-enum"
    gem "haml-rails"
    gem 'simple_form'
    gem 'bootstrap_form'
    gem 'mongoid-slug'
    gem 'carrierwave-mongoid', :require => 'carrierwave/mongoid'
    gem 'mini_magick'
    gem 'uglifier', '>= 1.3.0'
    gem 'jquery-rails'
    gem 'turbolinks'
    gem 'jbuilder', '~> 2.0'
    gem 'rest-client'
    gem 'execjs'
    gem 'therubyracer'
    gem 'redis-rails'
    gem 'stripe', :git => 'https://github.com/stripe/stripe-ruby'
    gem 'mongoid-versioning'
    gem 'rack-cors'
    gem 'bcrypt', '~> 3.1.7'
    gem 'sidekiq', '~> 3.4.2'
    gem 'sidetiq'
    gem 'sinatra', '>= 1.3.0', :require => nil
    gem 'puma'
    gem 'paypal-sdk-rest'
    gem "mongoid-paperclip", :require => "mongoid_paperclip"
    gem 'aws-sdk', '~> 1.3.4'
    gem 'money-rails'
    gem 'geocoder'
    gem 'kaminari'
    gem 'mongoid_auto_increment'
    gem 'aws-sdk-rails'
    gem 'mailcatcher'

    group :development, :test do
        gem "faker", "~> 1.4.3"
        gem 'guard-rails'
        gem 'spork-rails'
        gem 'guard-spork'
        gem 'childprocess'
        gem 'spring-commands-rspec'
        gem 'rspec-rails'
        gem 'guard-rspec'
        gem 'rb-fsevent', :require => false
        gem 'guard-livereload', require: false
        gem 'cucumber-rails', :require => false
        gem 'database_cleaner'
        gem 'byebug'
        gem 'web-console', '~> 2.0'
        gem 'spring'
        gem 'mongoid-rspec'
        gem 'capybara'
        gem 'factory_girl_rails'
        gem 'capistrano',         require: false
        gem 'capistrano-rvm',     require: false
        gem 'capistrano-rails',   require: false
        gem 'capistrano-bundler', require: false
        gem 'capistrano3-puma',   require: false
        gem 'capistrano-secrets-yml', '~> 1.0.0'
    end

    group :doc do
        gem 'sdoc', '~> 0.4.0'
    end

    group :production do
        gem 'rails_12factor', '0.0.2'
    end

2 个答案:

答案 0 :(得分:1)

这不是那么优雅的解决方案,但它有效:

转到app/config/initializers并创建文件date_format.rb。填写:

Time::DATE_FORMATS[:default] = "%d/%m/%Y"
Date::DATE_FORMATS[:default] = "%d/%m/%Y"

您的模型现在应该如下所示:

  def self.to_csv

    attributes = %w{ customer_name created_at order_id currency discount subtotal_tax total }

    CSV.generate(headers: true) do |csv|
         csv << attributes

         datetime = DateTime.now

         all.each do |order|
           if order['created_at']
             order['created_at'] =  datetime.to_formatted_s(:default)
           end
           csv << attributes.map{ |attr| order.send(attr) }
         end
       end
  end

如果您想添加时间,只需将date_format.rb更新为:

 Time::DATE_FORMATS[:default] = "%d/%m/%Y %H:%M:%S"
 Date::DATE_FORMATS[:default] = "%d/%m/%Y %H:%M:%S"

这非常具有挑战性。我希望它有所帮助。

reference

修改

您的模型还有一个解决方案。如果这对您有用,请告诉我。只需将上面的代码替换为前一代码即可。我非常好奇:

def self.to_csv

    attributes = %w{ customer_name created_at order_id currency discount subtotal_tax total }

    CSV.generate(headers: true) do |csv|
      csv << attributes
      all.each do |order|
        if order['created_at']
          order['created_at'] = order.created_at.strftime("%d/%m/%Y")
        end
        csv << attributes.map{ |attr| order.send(attr) }
      end
    end

  end

答案 1 :(得分:0)

测试当前项目。

第一个在没有更新模型实例(db数据)的情况下无法工作,第二个循环只是映射数据。更容易操作。

  def self.to_csv
    attributes = %w{ customer_name created_at order_id currency discount subtotal_tax total }
    CSV.generate(headers: true) do |csv|
      csv << attributes
      all.each do |order|
        csv << attributes.map do |attr| 
          if attr == 'created_at'
            order.created_at.strftime("%d/%m/%Y")
          else
            order.send(attr)
          end
        end
      end
    end
  end