Rails - 如果存在空白字段,则导出CSV失败

时间:2016-10-19 14:10:15

标签: ruby-on-rails csv

我的Rails应用程序中有代码,允许我导出CSV文件。除非有记录中包含没有值的字段,否则它可以正常工作。在那种情况下它失败了。作为一个例子,我得到的具体失败是说“没有方法错误”,它特别引用“address_line_1”,因为有些用户没有address_line_1。这只是一个例子。确实应该保护所有领域免受潜在的空白。这是代码:

def download_kids_csv

    @csv_headers = ['First',
                    'Last',
                    'Child First',
                    'Child Last',
                    'Parent Email',
                    'School',
                    'Class',
                    'Address',
                    'City',
                    'State',
                    'Zip',
                    'Parent Phone']

    @kid_data = []

    @school = School.find(params[:school_id])

    @school.classrooms.each do |classroom|
        classroom.kids.includes(:users).each do |kid|
            kid.users.each do |parent|
                @kid_data << {
                    first: parent.first_name,
                    last: parent.last_name,
                    child_first: kid.first_name,
                    child_last: kid.last_name,
                    parent_email: parent.email,
                    school: @school.name,
                    class: classroom.classroom_name,
                    address: parent.addresses.first.address_line_1,
                    city: parent.addresses.first.city,
                    state: parent.addresses.first.state,
                    zip: parent.addresses.first.zip_code,
                    parent_phone: parent.phones.first.phone_number
                }
            end
        end
    end

    respond_to do |format|
        format.csv do
          headers['Content-Disposition'] = "attachment; filename=\"#{@school.name.downcase.gsub(' ', '-')}-data.csv\""
          headers['Content-Type'] ||= 'text/csv'
        end
    end
end

3 个答案:

答案 0 :(得分:0)

好的,你得到的问题是因为你在nil值上调用方法。

例如,当你这样做时:

 kid.first_name

并且孩子没有你这样做

nil.first_name

nil没有实现first_name方法,因此会抛出错误。你可以做些什么来规避这个(它有点难看)就是这个

kid.try(:first_name)

这将阻止您形成获取这些方法缺失的错误

对于那些长链,您可以执行以下操作

parent.try(:addresses).try(:first).try(:zip_code)

这可以为您节省很多麻烦,但问题的根本原因是数据完整性,如果您确保数据不是空白,则不必执行所有这些操作。然而,我确实在现实世界中理解说起来容易做起来难。我可以给你一个关于The Law of Demeter的演讲,以及你如何不跨越对象来访问他们的属性,以及代码如何闻到错误的数据组织,但它是一个电子表格,有时你只需要数据。祝你好运!

答案 1 :(得分:0)

要构建早期的答案,如果你使用的是Ruby 2.3,你也可以利用所谓的孤独运算符&.

示例如下所示:kid&.first_name

如果你还没有使用那个版本的ruby,那么有一个很好的gem可以帮助你解决这个比.try更强大的情况。

使用该gem,您的代码看起来像kid.andand.first_name。在这种情况下可能有些过分,但这里的区别在于,如果first_name不是nil,它只会执行kid方法调用。对于较长的链parent.address.first.zip_code,这意味着如果parent为nil,则函数链会立即退出,而不是通过try调用所有不同的属性。

答案 2 :(得分:0)

是否可以使用除非或其他条件?

unless parent.addresses.first.address_line_1.blank?
 address: parent.addresses.first.address_line_1,
end

if parent.addresses.first.address_line_1 != nil
  address: parent.addresses.first.address_line_1,
else
 address: nil || "address is empty"
end