Rails 5 - 导出到XL / CSV但通过关联

时间:2016-12-10 23:08:37

标签: ruby-on-rails excel csv

我一直在关注CSV / Excel导出Railscast,但我对关联逻辑有点问题。

CSV混淆/问题

Collection Model我有

class Collection < ApplicationRecord
  belongs_to :user
  has_many :card_collections
  has_many :cards, through: :card_collections

  def self.to_csv
    attributes = %w{name}

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

      all.each do |collection|
        csv << attributes.map{ |attr| collection.send(attr) }
      end
    end
  end

  # validates :user_id, presence: true
end

CSV导出

name
Demo 2
HEHHEHEEHHE

name是列名 演示2是第一个Collection HEHHEHEEHHE是第二个系列

我需要更多信息,但是一旦我得到“一个”参数,我就可以从那里开始。但这不起作用。'name'将返回所有集合的名称,这根本不是我想要的,但我也试图获取有关集合中'卡'的信息(由cards_collection引用) ) 举个例子 - 在控制台中我会输入: c = Collection.last c.cards.first.name我会获得第一张名片。 我不确定我是否应该在Card_collections控制器,Cards控制器或者什么中创建这个self.to_csv函数。我通过关联找到了很多关于CSV的类似问题,但没有任何东西能让我找到解决方案

Excel混淆

<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
  xmlns:o="urn:schemas-microsoft-com:office:office"
  xmlns:x="urn:schemas-microsoft-com:office:excel"
  xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
  xmlns:html="http://www.w3.org/TR/REC-html40">
  <Worksheet ss:Name="Card Collection">
    <Table>
      <Row>
        <Cell><Data ss:Type="String">Name</Data></Cell>
        <Cell><Data ss:Type="String">Text</Data></Cell>
        <Cell><Data ss:Type="String">Set</Data></Cell>
      </Row>
    <% @collection.card_collections.each do |collection| %>
      <Row>
        <Cell><Data ss:Type="String"><%= collection.card.name %></Data></Cell>
        <Cell><Data ss:Type="String"><%= collection.card.text %></Data></Cell>
        <Cell><Data ss:Type="String"><%= collection.card.set %></Data></Cell>
      </Row>
    <% end %>
    </Table>
  </Worksheet>
</Workbook>

是一个示例脚本 - 我实际上将它包装在'each'中,因为如果他们选择Excel,我将允许他们每个'集合'获得一张。

为了让您了解这种关系,我的 Collection View 看起来像 -

<p id="notice"><%= notice %></p>
<div class="center"><%= @collection.name %></div><br />
<div class="center">Made By: 
<strong>
  <% if @collection.public %>
    <%= link_to @collection.user.name, {:controller => "users", :action => "show", :id => @collection.user.id} %><br />
  <% else %>
    Anonymous<br />
  <% end %>
</strong>
Total Cards: <%= @collection.card_collections.sum(:card_counts) %>
Distinct Cards: <%= @collection.card_collections.count %> <br />
</div>
  <% @collection.card_collections.in_groups_of(3, false).each do |group| %>
  <div class='row'>
    <% group.each do |card| %>
      <div class='col-sm-6 col-md-4'>
        <%= image_tag(card.card.image_url, class: "img-responsive") %>
        <h3>
          <%= link_to card.card.name, {:controller => "cards", :action => "show", :id => card.card.id }%>
        </h3>
        <div><%= card_text_swap(card.card.text) %></div>
        <div><span class='cardLabel'>Set</span>: <i class="ss ss-<%= card.card.set.downcase %> ss-3x ss-<%= card.card.rarity.downcase %>"></i>  
               <span class="setName"><%= card.card.setName %></span>
        </div>
        <div>Total in Collection: <%= card.card_counts %></div>
      </div>
    <% end %>
  </div>
  <% end %>


<%= link_to 'Edit', edit_collection_path(@collection) %> |
<%= link_to 'Back', collections_path %>

我最初在制作视图时苦苦挣扎,但终于让它工作了,我试图在Excel导出中使用相同的逻辑,但它没有正确渲染。 (立即没有错误,所以我认为这可能是我的失败。)

其他信息所有这些都存储在ActiveDirectory中,并且当前正在呈现给视图。不确定我应该提供什么其他信息。

新Excel问题

Collections_Controller

  def show
    @collection = Collection.find(params[:id])
    respond_to do |format|
      format.html
      format.csv { render text: @collection.to_csv }
      format.xls { send_data @collection.to_csv(col_sep: "\t") }
    end
  end

查看

  <%= link_to "CSV", collection_path(format: "csv") %> |
  <%= link_to "Excel", collection_path(format: "xls") %>

CSV现在正在运行 - Excel不是。

提供错误:

ArgumentError in CollectionsController#show
wrong number of arguments (given 1, expected 0)

1 个答案:

答案 0 :(得分:2)

&#34; def self.to_csv&#34;定义一个类方法。如果要列出给定Collection的卡片,则需要定义并调用(在集合控制器的show方法中)实例方法。

所以我用以下方式更改了你的to_csv:

def to_csv
  attributes = %w{name}

  CSV.generate(headers: true) do |csv|
    csv << attributes
    cards.each do |card|
      csv << attributes.map{ |attr| card.send(attr) }
    end
  end
end

这是如何在控制器中调用to_csv:

class CollectionsController < ApplicationController
  def show
    @collection = Collection.find(params[:id])
    respond_to do |format|
      format.html
      format.csv { render text: @collection.to_csv }
    end
  end
end

for Excel:

<?xml version="1.0"?>
<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"
  xmlns:o="urn:schemas-microsoft-com:office:office"
  xmlns:x="urn:schemas-microsoft-com:office:excel"
  xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"
  xmlns:html="http://www.w3.org/TR/REC-html40">
  <Worksheet ss:Name="Card Collection">
    <Table>
      <Row>
        <Cell><Data ss:Type="String">Name</Data></Cell>
        <Cell><Data ss:Type="String">Text</Data></Cell>
        <Cell><Data ss:Type="String">Set</Data></Cell>
      </Row>
    <% @collection.cards.each do |card| %>
      <Row>
        <Cell><Data ss:Type="String"><%= card.name %></Data></Cell>
        <Cell><Data ss:Type="String"><%= card.text %></Data></Cell>
        <Cell><Data ss:Type="String"><%= card.set %></Data></Cell>
      </Row>
    <% end %>
    </Table>
  </Worksheet>
</Workbook>

通常当您想要访问给定@collection的卡时,只需使用cards关系,当您访问给定卡的属性时,您将不需要额外的.card