2

この質問に似ています。私はRails 3.2を使用しているので、FasterCSVは必要ないことを知っています。私がやろうとしているのは、すべてのデータをCSVファイルにエクスポートすることです。データには、7 つの has_many の子を持つ親モデルがあり、各 has_many の子に 1 つ以上のレコードがある場合があります。例えば。

class ParentModel < ActiveRecord::Base

has_many :child_1

has_many :child_2

has_many :child_3

それで

class Child1 < ActiveRecord::Base

所属先:親モデル

class Child2 < ActiveRecord::Base

所属先:親モデル

class Child3 < ActiveRecord::Base

所属先:親モデル

そのため、多数の ParentModel レコードがあり、ParentModel レコードごとに異なる数の Child1、Child2、および Child3 レコードが存在する可能性があります。ParentModel に Child のレコードが 1 つしかない場合、CSV の最初の行を動的に把握し、CSV にデータを入力して NULL を挿入するにはどうすればよいですか? これを行う効率的な方法はありますか、それとも多くのループが必要ですか?

たとえば、データベース全体で、ParentModel に含まれる Child1 レコードの最大数は 2 であり、ParentModel の最大の Child2 レコードは 1 つだけであり、Child3 レコードは 3 つあるとします。したがって、CSV の最初の行は次のようになります。

ParentModel.field1、ParentModel.field1、Child1.field1、Child1.field2、Child1(record#2).field1、Child1(record#2).field2、Child2.field1、Child2.field2、Child3.field1、Child3.field2、 Child3(record#2).field1, Child3(record#2).field2, Child3(record#3).field1, Child3(record#3).field2

ただし、別の Child1 が ParentModel に追加されるため、次にエクスポートを実行するときにそれが判断され、CSV の最初の行は次のようになります。

ParentModel.field1、ParentModel.field1、Child1.field1、Child1.field2、Child1(record#2).field1、Child1(record#2).field2、Child1(record#3).field1、Child1(record#3)。 field2, Child2.field1, Child2.field2,Child3.field1, Child3.field2, Child3(record#2).field1, Child3(record#2).field2, Child3(record#3).field1, Child3(record#3) .field2

または....これを書いた後、私はこれを複雑にしすぎていて、これを行うためのスムーズな「レールの方法」があるのではないかと思っていますか?

ありがとう!

4

1 に答える 1

1

基本的に、親モデルが持つ子の最大数を把握する必要がありました。次に、CSV の各行のレコードをエクスポートするときに、子モデルの列に-、最も数の多いレコードほど多くの子がない場合は、子モデルを埋めます。(私は知っています、少し混乱していますよね?)

私の場合、複数の子レコードを持つことができる親モデルがあります。

class Parent < ActiveRecord::Base
  has_many :childs
...

class Child < ActiveRecord::Base
  belongs_to :parents
...

で、1 つの親ParentsControllerの最大数を見つけ、childsCSV のヘッダーの列名を取得します。

class ParentsController < ApplicationController

def download    

@parents = Parent.all
# find maximum number of children any parent has. Make sure to convert to integer.
@max_children = Child.select('parent_id, COUNT(parent_id)').group(:parent_id).order('COUNT(parent_id) DESC').first.count.to_i

@parent_columns = Parent.column_names
@child_columns = Child.column_names

@streaming = true
@filename = "export.csv"

respond_to do |format|
  format.csv
end

次にdownload.csv.csvbuilder、列名のヘッダーと、クエリから親が持つ可能性のある子の最大数のヘッダーを含む CSV ファイルを作成します。

header = Array.new
@parent_columns.each do |column_name| 
  header << column_name.humanize 
end 

if @child_columns
    i = 0
    while i < @max_children do 
      @child_columns.each do |column_name| 
        header << "Child #{i+1} " + column_name.humanize 
      end
      i += 1
    end
end

csv << header.flatten

@parents.each do |parent|

  parent_record = Array.new

  parent_record << parent.attributes.values_at(*@parent_columns)

## NOTE: Here is the answer

if @child_columns
  if parent.childs.first.nil?
    i = 0
    while i < @max_children do 
        @child_columns.each do |column_name|
          parent_record << "-"
        end
      i += 1
    end
  elsif !parent.childs.first.nil?
    how_many_blanks = @max_children - parent.childs.length
    parent.childs.each do |child| 
      @child_columns.each do |child_column|
        parent_record << child.attributes.values_at(*child_column)
      end
    end
    i = 0
    while i < how_many_blanks do 
        @child_columns.each do |column_name|
          parent_record << "-"
        end
      i += 1
    end
  end
end

  csv << parent_record.flatten

end 

これが役立つことを願っています!

于 2014-11-18T18:11:41.637 に答える