Full Code of comma-csv/comma for AI

master 0f639466331e cached
48 files
55.7 KB
16.7k tokens
98 symbols
1 requests
Download .txt
Repository: comma-csv/comma
Branch: master
Commit: 0f639466331e
Files: 48
Total size: 55.7 KB

Directory structure:
gitextract_uknkcqm5/

├── .coveralls.yml
├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── .rspec
├── .rubocop.yml
├── .rubocop_todo.yml
├── .travis.yml
├── Appraisals
├── Gemfile
├── MIT-LICENSE
├── README.md
├── Rakefile
├── comma.gemspec
├── gemfiles/
│   ├── active6.0.6.gemfile
│   ├── active6.1.7.6.gemfile
│   ├── active7.0.8.gemfile
│   ├── active7.1.3.gemfile
│   ├── rails6.0.6.gemfile
│   ├── rails6.1.7.6.gemfile
│   ├── rails7.0.8.gemfile
│   └── rails7.1.3.gemfile
├── init.rb
├── lib/
│   ├── comma/
│   │   ├── array.rb
│   │   ├── data_extractor.rb
│   │   ├── data_mapper_collection.rb
│   │   ├── extractor.rb
│   │   ├── generator.rb
│   │   ├── header_extractor.rb
│   │   ├── mongoid.rb
│   │   ├── object.rb
│   │   ├── relation.rb
│   │   └── version.rb
│   └── comma.rb
└── spec/
    ├── comma/
    │   ├── comma_spec.rb
    │   ├── data_extractor_spec.rb
    │   ├── header_extractor_spec.rb
    │   └── rails/
    │       ├── active_record_spec.rb
    │       ├── data_mapper_collection_spec.rb
    │       └── mongoid_spec.rb
    ├── controllers/
    │   └── users_controller_spec.rb
    ├── non_rails_app/
    │   └── ruby_classes.rb
    ├── rails_app/
    │   ├── active_record/
    │   │   ├── config.rb
    │   │   └── models.rb
    │   ├── data_mapper/
    │   │   └── config.rb
    │   ├── mongoid/
    │   │   └── config.rb
    │   ├── rails_app.rb
    │   └── tmp/
    │       └── .gitkeep
    └── spec_helper.rb

================================================
FILE CONTENTS
================================================

================================================
FILE: .coveralls.yml
================================================
service_name: travis-ci


================================================
FILE: .github/workflows/build.yml
================================================
name: Build
on: [push, pull_request]
jobs:
  build:
    strategy:
      matrix:
        ruby: ['3.0', '3.1', '3.2', '3.3']
        gemfile: ['active6.0.6', 'active6.1.7.6', 'active7.0.8', 'active7.1.3', 'rails6.0.6', 'rails6.1.7.6', 'rails7.0.8', 'rails7.1.3']
    runs-on: ubuntu-latest
    env:
      BUNDLE_GEMFILE: ${{ github.workspace }}/gemfiles/${{ matrix.gemfile }}.gemfile
      RUBY_OPT: --disable=did_you_mean
    services:
      mongodb:
        image: mongo:4.4.10
        ports:
          - 8081:8081
    steps:
      - uses: actions/checkout@v3
      - uses: ruby/setup-ruby@v1
        with:
          ruby-version: ${{ matrix.ruby }}
          bundler-cache: true
          cache-version: 1
      - run: bundle install --jobs 2 --retry 3
      - run: bundle exec rubocop -P
      - run: bundle exec rspec -f d spec


================================================
FILE: .gitignore
================================================
pkg/*
.*.swp
*~
.bundle
spec/rails_app/log
spec/rails_app/db/development.sqlite*
.rbx/
.ruby-*
coverage/*


================================================
FILE: .rspec
================================================
--colour


================================================
FILE: .rubocop.yml
================================================
inherit_from: .rubocop_todo.yml

require: rubocop-performance

AllCops:
  DisplayCopNames: true
  Exclude:
    - 'gemfiles/**/*'
    - 'vendor/**/*'
  NewCops: enable
  TargetRubyVersion: 2.5

Layout/LineLength:
  IgnoreCopDirectives: true
  Max: 120

Naming/FileName:
  Exclude:
    - 'Appraisals'

Naming/VariableNumber:
  EnforcedStyle: snake_case



================================================
FILE: .rubocop_todo.yml
================================================
# This configuration was generated by
# `rubocop --auto-gen-config`
# on 2024-01-20 09:02:51 UTC using RuboCop version 1.30.1.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
# versions of RuboCop, may require this file to be generated again.

# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Include.
# Include: **/*.gemspec
Gemspec/DeprecatedAttributeAssignment:
  Exclude:
    - 'comma.gemspec'

# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: Include.
# Include: **/*.gemspec
Gemspec/RequireMFA:
  Exclude:
    - 'comma.gemspec'

# Offense count: 1
# Configuration parameters: Include.
# Include: **/*.gemspec
Gemspec/RequiredRubyVersion:
  Exclude:
    - 'comma.gemspec'

# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EmptyLineBetweenMethodDefs, EmptyLineBetweenClassDefs, EmptyLineBetweenModuleDefs, AllowAdjacentOneLineDefs, NumberOfEmptyLines.
Layout/EmptyLineBetweenDefs:
  Exclude:
    - 'spec/rails_app/rails_app.rb'

# Offense count: 4
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: AllowAliasSyntax, AllowedMethods.
# AllowedMethods: alias_method, public, protected, private
Layout/EmptyLinesAroundAttributeAccessor:
  Exclude:
    - 'spec/comma/comma_spec.rb'

# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Layout/SpaceAroundMethodCallOperator:
  Exclude:
    - 'spec/controllers/users_controller_spec.rb'

# Offense count: 17
# Configuration parameters: AllowedMethods.
# AllowedMethods: enums
Lint/ConstantDefinitionInBlock:
  Exclude:
    - 'spec/comma/comma_spec.rb'
    - 'spec/comma/rails/active_record_spec.rb'
    - 'spec/comma/rails/data_mapper_collection_spec.rb'
    - 'spec/comma/rails/mongoid_spec.rb'

# Offense count: 4
# Configuration parameters: AllowComments, AllowEmptyLambdas.
Lint/EmptyBlock:
  Exclude:
    - 'spec/comma/comma_spec.rb'
    - 'spec/comma/rails/data_mapper_collection_spec.rb'

# Offense count: 1
Lint/MissingSuper:
  Exclude:
    - 'spec/comma/comma_spec.rb'

# Offense count: 1
# This cop supports unsafe autocorrection (--autocorrect-all).
Lint/NonDeterministicRequireOrder:
  Exclude:
    - 'spec/spec_helper.rb'

# Offense count: 2
# Configuration parameters: IgnoredMethods, CountRepeatedAttributes.
Metrics/AbcSize:
  Max: 22

# Offense count: 3
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, IgnoredMethods.
Metrics/MethodLength:
  Max: 16

# Offense count: 2
# Configuration parameters: EnforcedStyle, AllowedIdentifiers, AllowedPatterns.
# SupportedStyles: snake_case, camelCase
Naming/VariableName:
  Exclude:
    - 'spec/comma/comma_spec.rb'

# Offense count: 14
# This cop supports safe autocorrection (--autocorrect).
# Configuration parameters: EnforcedStyle, ProceduralMethods, FunctionalMethods, IgnoredMethods, AllowBracesOnProceduralOneLiners, BracesRequiredMethods.
# SupportedStyles: line_count_based, semantic, braces_for_chaining, always_braces
# ProceduralMethods: benchmark, bm, bmbm, create, each_with_object, measure, new, realtime, tap, with_object
# FunctionalMethods: let, let!, subject, watch
# IgnoredMethods: lambda, proc, it
Style/BlockDelimiters:
  Exclude:
    - 'spec/comma/comma_spec.rb'
    - 'spec/comma/data_extractor_spec.rb'
    - 'spec/comma/header_extractor_spec.rb'

# Offense count: 11
# Configuration parameters: AllowedConstants.
Style/Documentation:
  Exclude:
    - 'spec/**/*'
    - 'test/**/*'
    - 'lib/comma/array.rb'
    - 'lib/comma/data_extractor.rb'
    - 'lib/comma/data_mapper_collection.rb'
    - 'lib/comma/extractor.rb'
    - 'lib/comma/generator.rb'
    - 'lib/comma/header_extractor.rb'
    - 'lib/comma/mongoid.rb'
    - 'lib/comma/object.rb'
    - 'lib/comma/relation.rb'

# Offense count: 3
Style/MissingRespondToMissing:
  Exclude:
    - 'lib/comma/data_extractor.rb'
    - 'lib/comma/header_extractor.rb'

# Offense count: 1
# This cop supports safe autocorrection (--autocorrect).
Style/RedundantBegin:
  Exclude:
    - 'spec/spec_helper.rb'

# Offense count: 6
# This cop supports unsafe autocorrection (--autocorrect-all).
# Configuration parameters: Mode.
Style/StringConcatenation:
  Exclude:
    - 'spec/comma/comma_spec.rb'
    - 'spec/comma/rails/active_record_spec.rb'
    - 'spec/spec_helper.rb'


================================================
FILE: .travis.yml
================================================
sudo: false

services: mongodb

language: ruby
cache: bundler
rvm:
  - 2.4.10
  - 2.5.8
  - 2.6.6
  - 2.7.2
gemfile:
  - gemfiles/active5.0.7.2.gemfile
  - gemfiles/active5.1.7.gemfile
  - gemfiles/active5.2.4.3.gemfile
  - gemfiles/active6.0.3.1.gemfile
  - gemfiles/active6.1.0.gemfile
  - gemfiles/rails5.0.7.2.gemfile
  - gemfiles/rails5.1.7.gemfile
  - gemfiles/rails5.2.4.3.gemfile
  - gemfiles/rails6.0.3.1.gemfile
  - gemfiles/rails6.1.0.gemfile
  - gemfiles/railsedge.gemfile
matrix:
  exclude:
    - rvm: 2.4.10
      gemfile: gemfiles/active6.0.3.1.gemfile
    - rvm: 2.4.10
      gemfile: gemfiles/active6.1.0.gemfile
    - rvm: 2.4.10
      gemfile: gemfiles/rails6.0.3.1.gemfile
    - rvm: 2.4.10
      gemfile: gemfiles/rails6.1.0.gemfile
    - rvm: 2.4.10
      gemfile: gemfiles/railsedge.gemfile
    - rvm: 2.5.8
      gemfile: gemfiles/railsedge.gemfile
  fast_finish: true
before_install:
  - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
  - gem install bundler -v '< 2'
script:
  - bundle exec rubocop -P
  - bundle exec rspec -f d spec


================================================
FILE: Appraisals
================================================
# frozen_string_literal: true

appraise 'rails6.0.6' do
  gem 'rails', '6.0.6'
  gem 'rspec-rails'
  gem 'test-unit'
end

appraise 'active6.0.6' do
  gem 'activesupport', '6.0.6'
  gem 'activerecord', '6.0.6'
end

appraise 'rails6.1.7.6' do
  gem 'rails', '6.1.7.6'
  gem 'rspec-rails'
  gem 'test-unit'
end

appraise 'active6.1.7.6' do
  gem 'activesupport', '6.1.7.6'
  gem 'activerecord', '6.1.7.6'
end

appraise 'rails7.0.8' do
  gem 'rails', '7.0.8'
  gem 'rspec-rails'
end

appraise 'active7.0.8' do
  gem 'activesupport', '7.0.8'
  gem 'activerecord', '7.0.8'
end

appraise 'rails7.1.3' do
  gem 'rails', '7.1.3'
  gem 'rspec-rails'
end

appraise 'active7.1.3' do
  gem 'activesupport', '7.1.3'
  gem 'activerecord', '7.1.3'
end


================================================
FILE: Gemfile
================================================
# frozen_string_literal: true

source 'https://rubygems.org'

gemspec

gem 'coveralls', require: false
gem 'rubocop', '~> 1.30.0', require: false
gem 'rubocop-performance', require: false
gem 'sqlite3'


================================================
FILE: MIT-LICENSE
================================================
Copyright (c) 2009 Marcus Crafter

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


================================================
FILE: README.md
================================================
# Comma

A library to generate comma seperated value (CSV) for Ruby objects like ActiveRecord and Array

[![Gem Version](https://badge.fury.io/rb/comma.svg)](http://badge.fury.io/rb/comma) [![Build Status](https://github.com/comma-csv/comma/actions/workflows/build.yml/badge.svg)](https://github.com/comma-csv/comma/actions/workflows/build.yml) [![Code Climate](https://codeclimate.com/github/comma-csv/comma.svg)](https://codeclimate.com/github/comma-csv/comma)

## Getting Started

### Prerequisites

You need to use ruby 3.0 or later. If you generate CSV from ActiveRecord models, you need to have ActiveRecord 6.0 or later.

### Installing

Comma is distributed as a gem, best installed via Bundler.

Include the gem in your Gemfile:

```ruby
gem 'comma', '~> 4.8.0'
```

Or, if you want to live life on the edge, you can get master from the main comma repository:

```ruby
gem 'comma',  git: 'git://github.com/comma-csv/comma.git'
```

Then, run `bundle install`.

### Usage

See [this page](https://github.com/comma-csv/comma/wiki) for usages.

## Running the tests

To run the test suite across multiple gem file sets, we're using [Appraisal](https://github.com/thoughtbot/appraisal), use the following commands:

```sh
$ bundle exec appraisal install
$ bundle exec appraisal rake spec

```

## Contributing

## Versioning

We use [SemVer](http://semver.org/) for versioning. For the versions available, see the [tags on this repository](https://github.com/comma-csv/comma/tags).

## Authors

* Marcus Crafter - Initial work
* Tom Meier - Initial work
* Eito Katagiri

## License

This project is licensed under the MIT License - see the [MIT-LICENSE](https://github.com/comma-csv/comma/blob/master/MIT-LICENSE) file fore details.


================================================
FILE: Rakefile
================================================
# frozen_string_literal: true

require 'bundler/setup'
require 'bundler/gem_tasks'

require 'rspec/core/rake_task'
RSpec::Core::RakeTask.new(:spec) do |spec|
  spec.pattern = FileList['spec/**/*_spec.rb']
end

require 'rubocop/rake_task'
RuboCop::RakeTask.new

task default: :spec


================================================
FILE: comma.gemspec
================================================
# frozen_string_literal: true

$LOAD_PATH.push File.expand_path('lib', __dir__)
require 'comma/version'

Gem::Specification.new do |s|
  s.name        = 'comma'
  s.version     = Comma::VERSION
  s.authors     = ['Marcus Crafter', 'Tom Meier']
  s.email       = ['crafterm@redartisan.com', 'tom@venombytes.com']
  s.homepage    = 'http://github.com/comma-csv/comma'
  s.summary     = %(Ruby Comma Seperated Values generation library)
  s.description = %(Ruby Comma Seperated Values generation library)

  s.files         = `git ls-files`.split("\n")
  s.test_files    = `git ls-files -- {test,spec,features}/*`.split("\n")
  s.require_paths = ['lib']

  s.licenses = ['MIT']

  s.add_dependency 'activesupport', '>= 4.2.0'

  s.add_development_dependency 'appraisal', ['~> 1.0.0']
  s.add_development_dependency 'minitest', '5.14.4'
  s.add_development_dependency 'rake', '~> 13.0.1'
  s.add_development_dependency 'rspec', ['~> 3.5.0']
  s.add_development_dependency 'rspec-activemodel-mocks'
  s.add_development_dependency 'rspec-its'
end


================================================
FILE: gemfiles/active6.0.6.gemfile
================================================
# This file was generated by Appraisal

source "https://rubygems.org"

gem "coveralls", :require => false
gem "rubocop", "~> 1.30.0", :require => false
gem "rubocop-performance", :require => false
gem "sqlite3"
gem "activesupport", "6.0.6"
gem "activerecord", "6.0.6"

gemspec :path => "../"


================================================
FILE: gemfiles/active6.1.7.6.gemfile
================================================
# This file was generated by Appraisal

source "https://rubygems.org"

gem "coveralls", :require => false
gem "rubocop", "~> 1.30.0", :require => false
gem "rubocop-performance", :require => false
gem "sqlite3"
gem "activesupport", "6.1.7.6"
gem "activerecord", "6.1.7.6"

gemspec :path => "../"


================================================
FILE: gemfiles/active7.0.8.gemfile
================================================
# This file was generated by Appraisal

source "https://rubygems.org"

gem "coveralls", :require => false
gem "rubocop", "~> 1.30.0", :require => false
gem "rubocop-performance", :require => false
gem "sqlite3"
gem "activesupport", "7.0.8"
gem "activerecord", "7.0.8"

gemspec :path => "../"


================================================
FILE: gemfiles/active7.1.3.gemfile
================================================
# This file was generated by Appraisal

source "https://rubygems.org"

gem "coveralls", :require => false
gem "rubocop", "~> 1.30.0", :require => false
gem "rubocop-performance", :require => false
gem "sqlite3"
gem "activesupport", "7.1.3"
gem "activerecord", "7.1.3"

gemspec :path => "../"


================================================
FILE: gemfiles/rails6.0.6.gemfile
================================================
# This file was generated by Appraisal

source "https://rubygems.org"

gem "coveralls", :require => false
gem "rubocop", "~> 1.30.0", :require => false
gem "rubocop-performance", :require => false
gem "sqlite3"
gem "rails", "6.0.6"
gem "rspec-rails"
gem "test-unit"

gemspec :path => "../"


================================================
FILE: gemfiles/rails6.1.7.6.gemfile
================================================
# This file was generated by Appraisal

source "https://rubygems.org"

gem "coveralls", :require => false
gem "rubocop", "~> 1.30.0", :require => false
gem "rubocop-performance", :require => false
gem "sqlite3"
gem "rails", "6.1.7.6"
gem "rspec-rails"
gem "test-unit"

gemspec :path => "../"


================================================
FILE: gemfiles/rails7.0.8.gemfile
================================================
# This file was generated by Appraisal

source "https://rubygems.org"

gem "coveralls", :require => false
gem "rubocop", "~> 1.30.0", :require => false
gem "rubocop-performance", :require => false
gem "sqlite3"
gem "rails", "7.0.8"
gem "rspec-rails"

gemspec :path => "../"


================================================
FILE: gemfiles/rails7.1.3.gemfile
================================================
# This file was generated by Appraisal

source "https://rubygems.org"

gem "coveralls", :require => false
gem "rubocop", "~> 1.30.0", :require => false
gem "rubocop-performance", :require => false
gem "sqlite3"
gem "rails", "7.1.3"
gem "rspec-rails"

gemspec :path => "../"


================================================
FILE: init.rb
================================================
# frozen_string_literal: true

require 'comma'


================================================
FILE: lib/comma/array.rb
================================================
# frozen_string_literal: true

class Array
  def to_comma(style = :default)
    Comma::Generator.new(self, style).run(:each)
  end
end


================================================
FILE: lib/comma/data_extractor.rb
================================================
# frozen_string_literal: true

require 'comma/extractor'

module Comma
  class DataExtractor < Extractor
    class ExtractValueFromInstance
      def initialize(instance)
        @instance = instance
      end

      def extract(sym, &block)
        yield_block_with_value(extract_value(sym), &block)
      end

      private

      def yield_block_with_value(value, &block)
        block ? yield(value) : value
      end

      def extract_value(method)
        extraction_object.send(method)
      end

      def extraction_object
        @instance
      end
    end

    class ExtractValueFromAssociationOfInstance < ExtractValueFromInstance
      def initialize(instance, association_name)
        super(instance)
        @association_name = association_name
      end

      private

      def extraction_object
        @instance.send(@association_name) || null_association
      end

      def null_association
        @null_association ||= Class.new(Class.const_defined?(:BasicObject) ? ::BasicObject : ::Object) do
          def method_missing(_symbol, *_args, &_block)
            nil
          end
        end.new
      end
    end

    def method_missing(sym, *args, &block)
      @results << ExtractValueFromInstance.new(@instance).extract(sym, &block) if
        args.blank?

      args.each do |arg|
        case arg
        when Hash
          arg.each do |k, _v|
            @results << ExtractValueFromAssociationOfInstance.new(@instance, sym).extract(k, &block)
          end
        when Symbol
          @results << ExtractValueFromAssociationOfInstance.new(@instance, sym).extract(arg, &block)
        when String
          @results << ExtractValueFromInstance.new(@instance).extract(sym, &block)
        else
          raise "Unknown data symbol #{arg.inspect}"
        end
      end
    end

    def __static_column__(_header = nil, &block)
      @results << (block ? yield(@instance) : nil)
    end
  end
end


================================================
FILE: lib/comma/data_mapper_collection.rb
================================================
# frozen_string_literal: true

if defined?(DataMapper)
  module DataMapper
    class Collection
      def to_comma(style = :default)
        Comma::Generator.new(self, style).run(:each)
      end
    end
  end
end


================================================
FILE: lib/comma/extractor.rb
================================================
# frozen_string_literal: true

module Comma
  class Extractor
    def initialize(instance, style, formats)
      @instance = instance
      @style = style
      @formats = formats
      @results = []
    end

    def results
      instance_eval(&@formats[@style])
      @results.map { |r| convert_to_data_value(r) }
    end

    def id(*args, &block)
      method_missing(:id, *args, &block)
    end

    def __use__(style)
      # TODO: prevent infinite recursion
      instance_eval(&@formats[style])
    end

    private

    def convert_to_data_value(result)
      result.nil? ? result : result.to_s
    end
  end
end


================================================
FILE: lib/comma/generator.rb
================================================
# frozen_string_literal: true

module Comma
  class Generator
    def initialize(instance, style)
      @instance = instance
      @style    = style
      @options  = {}

      return unless @style.is_a?(Hash)

      @options                  = @style.clone
      @style                    = @options.delete(:style) || Comma::DEFAULT_OPTIONS[:style]
      @filename                 = @options.delete(:filename)
    end

    def run(iterator_method)
      if @filename
        CSV_HANDLER.open(@filename, 'w', **@options) { |csv| append_csv(csv, iterator_method) } && (return true)
      else
        CSV_HANDLER.generate(**@options) { |csv| append_csv(csv, iterator_method) }
      end
    end

    private

    def append_csv(csv, iterator_method)
      return '' if @instance.empty?

      csv << @instance.first.to_comma_headers(@style) unless
        @options.key?(:write_headers) && !@options[:write_headers]
      @instance.send(iterator_method) do |object|
        csv << object.to_comma(@style)
      end
    end
  end
end


================================================
FILE: lib/comma/header_extractor.rb
================================================
# frozen_string_literal: true

require 'comma/extractor'
require 'active_support'
require 'active_support/core_ext/class/attribute'
require 'active_support/core_ext/date_time/conversions'
require 'active_support/core_ext/object/blank'
require 'active_support/core_ext/string/inflections'

module Comma
  class HeaderExtractor < Extractor
    class_attribute :value_humanizer

    DEFAULT_VALUE_HUMANIZER = lambda do |value, _model_class|
      value.is_a?(String) ? value : value.to_s.humanize
    end
    self.value_humanizer = DEFAULT_VALUE_HUMANIZER

    def method_missing(sym, *args, &_block)
      model_class = @instance.class
      @results << value_humanizer.call(sym, model_class) if args.blank?
      args.each do |arg|
        case arg
        when Hash
          arg.each do |_k, v|
            @results << value_humanizer.call(v, get_association_class(model_class, sym))
          end
        when Symbol
          @results << value_humanizer.call(arg, get_association_class(model_class, sym))
        when String
          @results << value_humanizer.call(arg, model_class)
        else
          raise "Unknown header symbol #{arg.inspect}"
        end
      end
    end

    def __static_column__(header = '', &_block)
      @results << header
    end

    private

    def get_association_class(model_class, association)
      return unless model_class.respond_to?(:reflect_on_association)

      begin
        model_class.reflect_on_association(association)&.klass
      rescue ArgumentError, NameError
        # Since Rails 5.2, ArgumentError is raised.
        nil
      end
    end
  end
end


================================================
FILE: lib/comma/mongoid.rb
================================================
# frozen_string_literal: true

# Conditionally set to_comma on Mongoid records if mongoid gem is installed
begin
  require 'mongoid'

  module Mongoid
    class Criteria
      def to_comma(style = :default)
        Comma::Generator.new(self, style).run(:each)
      end
    end
  end
rescue LoadError => e
  warn e.inspect
end


================================================
FILE: lib/comma/object.rb
================================================
# frozen_string_literal: true

require 'comma/data_extractor'
require 'comma/header_extractor'

class Object
  class_attribute :comma_formats

  class << self
    def comma(style = :default, &block)
      (self.comma_formats ||= {})[style] = block
    end

    def inherited(subclass)
      super
      subclass.comma_formats = self.comma_formats ? self.comma_formats.dup : {}
    end
  end

  def to_comma(style = :default)
    extract_with(Comma::DataExtractor, style)
  end

  def to_comma_headers(style = :default)
    extract_with(Comma::HeaderExtractor, style)
  end

  private

  def extract_with(extractor_class, style = :default)
    raise_unless_style_exists(style)
    extractor_class.new(self, style, self.comma_formats).results
  end

  def raise_unless_style_exists(style)
    return if self.comma_formats && self.comma_formats[style]

    raise "No comma format for class #{self.class} defined for style #{style}"
  end
end


================================================
FILE: lib/comma/relation.rb
================================================
# frozen_string_literal: true

module ActiveRecord
  class Relation
    def to_comma(style = :default)
      iterator_method =
        if arel.ast.limit || !arel.ast.orders.empty?
          Rails.logger.warn { <<~WARN } if defined?(Rails)
            #to_comma is being used on a relation with limit or order clauses. Falling back to iterating with :each. This can cause performance issues.
          WARN
          :each
        else
          :find_each
        end
      Comma::Generator.new(self, style).run(iterator_method)
    end
  end
end


================================================
FILE: lib/comma/version.rb
================================================
# frozen_string_literal: true

module Comma
  VERSION = '4.8.0'
end


================================================
FILE: lib/comma.rb
================================================
# frozen_string_literal: true

require 'csv'
CSV_HANDLER = CSV

module Comma
  DEFAULT_OPTIONS = {
    write_headers: true,
    style: :default
  }.freeze
end

require 'active_support'
require 'active_support/lazy_load_hooks'
ActiveSupport.on_load(:active_record) do
  require 'comma/relation' if defined?(ActiveRecord::Relation)
end

ActiveSupport.on_load(:mongoid) do
  require 'comma/mongoid'
end

require 'comma/data_mapper_collection' if defined? DataMapper

require 'comma/generator'
require 'comma/array'
require 'comma/object'

# Load into Rails controllers
ActiveSupport.on_load(:action_controller) do
  if defined?(ActionController::Renderers) && ActionController::Renderers.respond_to?(:add)
    ActionController::Renderers.add :csv do |obj, options|
      filename    = options[:filename]  || 'data'
      extension   = options[:extension] || 'csv'
      mime_type = if Rails.version >= '5.0.0'
                    options[:mime_type] || Mime[:csv]
                  else
                    options[:mime_type] || Mime::CSV
                  end
      with_bom = options.delete(:with_bom) || false

      # Capture any CSV optional settings passed to comma or comma specific options
      csv_options = options.slice(*CSV_HANDLER::DEFAULT_OPTIONS.merge(Comma::DEFAULT_OPTIONS).keys)
      csv_options = csv_options.each_with_object({}) do |(k, v), h|
        # XXX: Convert string to boolean
        h[k] = case k
               when :write_headers
                 (v != 'false') if v.is_a?(String)
               else
                 v
               end
      end
      data = obj.to_comma(csv_options)
      data = "\xEF\xBB\xBF#{data}" if with_bom
      disposition = "attachment; filename=\"#{filename}.#{extension}\""
      send_data data, type: mime_type, disposition: disposition
    end
  end
end


================================================
FILE: spec/comma/comma_spec.rb
================================================
# frozen_string_literal: true

require File.dirname(__FILE__) + '/../spec_helper'

describe Comma do
  it 'should extend object to add a comma method' do
    expect(Object).to respond_to(:comma)
  end

  it 'should extend object to have a to_comma method' do
    expect(Object).to respond_to(:to_comma)
  end

  it 'should extend object to have a to_comma_headers method' do
    expect(Object).to respond_to(:to_comma_headers)
  end

  describe '.to_comma_header' do
    it 'should not crash (#94)' do
      klass = Class.new
      klass.instance_eval do
        attr_accessor :name

        comma :brief do
          name
        end
      end
      expect { klass.to_comma_headers(:brief) }.to_not raise_error
    end
  end
end

describe Comma, 'generating CSV' do # rubocop:disable Metrics/BlockLength
  before do
    @isbn = Isbn.new('123123123', '321321321')
    @book = Book.new('Smalltalk-80', 'Language and Implementation', @isbn)

    @books = []
    @books << @book
  end

  it 'should extend Array to add a #to_comma method which will return CSV content for objects within the array' do
    expected = "Title,Description,Issuer,ISBN-10,ISBN-13\nSmalltalk-80,Language and Implementation,ISBN,123123123,321321321\n" # rubocop:disable Layout/LineLength
    expect(@books.to_comma).to eq(expected)
  end

  it 'should return an empty string when generating CSV from an empty array' do
    expect([].to_comma).to eq('')
  end

  it 'should change the style when specified' do
    expect(@books.to_comma(:brief)).to eq("Name,Description\nSmalltalk-80,Language and Implementation\n")
  end

  describe 'with :filename specified' do
    after { File.delete('comma.csv') }

    it 'should write to the file' do
      @books.to_comma(filename: 'comma.csv')
      expected = "Title,Description,Issuer,ISBN-10,ISBN-13\nSmalltalk-80,Language and Implementation,ISBN,123123123,321321321\n" # rubocop:disable Layout/LineLength
      expect(File.read('comma.csv')).to eq(expected)
    end

    it 'should accept FasterCSV options' do
      @books.to_comma(filename: 'comma.csv', col_sep: ';', force_quotes: true)
      expected = "\"Title\";\"Description\";\"Issuer\";\"ISBN-10\";\"ISBN-13\"\n\"Smalltalk-80\";\"Language and Implementation\";\"ISBN\";\"123123123\";\"321321321\"\n" # rubocop:disable Layout/LineLength
      expect(File.read('comma.csv')).to eq(expected)
    end
  end

  describe 'with FasterCSV options' do
    it 'should not change when options are empty' do
      expected = "Title,Description,Issuer,ISBN-10,ISBN-13\nSmalltalk-80,Language and Implementation,ISBN,123123123,321321321\n" # rubocop:disable Layout/LineLength
      expect(@books.to_comma({})).to eq(expected)
    end

    it 'should accept the options in #to_comma and generate the appropriate CSV' do
      expected = "\"Title\";\"Description\";\"Issuer\";\"ISBN-10\";\"ISBN-13\"\n\"Smalltalk-80\";\"Language and Implementation\";\"ISBN\";\"123123123\";\"321321321\"\n" # rubocop:disable Layout/LineLength
      expect(@books.to_comma(col_sep: ';', force_quotes: true)).to eq(expected)
    end

    it 'should change the style when specified' do
      expect(@books.to_comma(style: :brief, col_sep: ';', force_quotes: true))
        .to eq("\"Name\";\"Description\"\n\"Smalltalk-80\";\"Language and Implementation\"\n")
    end
  end
end

describe Comma, 'defining CSV descriptions' do
  describe 'with an unnamed description' do
    before do
      class Foo
        comma do; end
      end
    end

    it 'should name the current description :default if no name has been provided' do
      expect(Foo.comma_formats).not_to be_empty
      expect(Foo.comma_formats[:default]).not_to be_nil
    end
  end

  describe 'with a named description' do
    before do
      class Bar
        comma do; end
        comma :detailed do; end
      end
    end

    it 'should use the provided name to index the comma format' do
      expect(Bar.comma_formats).not_to be_empty
      expect(Bar.comma_formats[:default]).not_to be_nil
      expect(Bar.comma_formats[:detailed]).not_to be_nil
    end
  end
end

describe Comma, 'to_comma data/headers object extensions' do # rubocop:disable Metrics/BlockLength
  describe 'with unnamed descriptions' do
    before do
      class Foo
        attr_accessor :content
        comma do; content; end

        def initialize(content)
          @content = content
        end
      end

      @foo = Foo.new('content')
    end

    it 'should return and array of data content, using the :default CSV description if none requested' do
      expect(@foo.to_comma).to eq(%w[content])
    end

    it 'should return and array of header content, using the :default CSV description if none requested' do
      expect(@foo.to_comma_headers).to eq(%w[Content])
    end

    it 'should return the CSV representation including header and content when called on an array' do
      expect(Array(@foo).to_comma).to eq("Content\ncontent\n")
    end
  end

  describe 'with named descriptions' do
    before do
      class Foo
        attr_accessor :content
        comma :detailed do; content; end

        def initialize(content)
          @content = content
        end
      end

      @foo = Foo.new('content')
    end

    it 'should return and array of data content, using the :default CSV description if none requested' do
      expect(@foo.to_comma(:detailed)).to eq(%w[content])
    end

    it 'should return and array of header content, using the :default CSV description if none requested' do
      expect(@foo.to_comma_headers(:detailed)).to eq(%w[Content])
    end

    it 'should return the CSV representation including header and content when called on an array' do
      expect(Array(@foo).to_comma(:detailed)).to eq("Content\ncontent\n")
    end

    it 'should raise an error if the requested description is not avaliable' do
      expect { @foo.to_comma(:bad) }.to raise_error(RuntimeError)
      expect { @foo.to_comma_headers(:bad) }.to raise_error(RuntimeError)
      expect { Array(@foo).to_comma(:bad) }.to raise_error(RuntimeError)
    end
  end

  describe 'with block' do # rubocop:disable Metrics/BlockLength
    before do
      class Foo
        attr_accessor :content, :created_at, :updated_at
        comma do
          content
          content('Truncated Content') { |i| i && i.length > 10 ? i[0..10] : '---' }
          created_at { |i| i&.to_formatted_s(:db) }
          updated_at { |i| i&.to_formatted_s(:db) }
          created_at 'Created Custom Label' do |i| i&.to_formatted_s(:short) end
          updated_at 'Updated at Custom Label' do |i| i&.to_formatted_s(:short) end
        end

        def initialize(content, created_at = Time.now, updated_at = Time.now)
          @content = content
          @created_at = created_at
          @updated_at = updated_at
        end
      end

      @time = Time.now
      @content = 'content ' * 5
      @foo = Foo.new @content, @time, @time
    end

    it 'should return yielded values by block' do
      _header, foo = Array(@foo).to_comma.split("\n")
      expected = [
        @content,
        @content[0..10],
        @time.to_formatted_s(:db),
        @time.to_formatted_s(:db),
        @time.to_formatted_s(:short),
        @time.to_formatted_s(:short)
      ].join(',')
      expect(foo).to eq(expected)
    end

    it 'should return headers with custom labels from block' do
      header, _foo = Array(@foo).to_comma.split("\n")
      expected = [
        'Content',
        'Truncated Content',
        'Created at',
        'Updated at',
        'Created Custom Label',
        'Updated at Custom Label'
      ].join(',')
      expect(header).to eq(expected)
    end

    it 'should put headers in place when forced' do
      header, _foo = Array(@foo).to_comma(write_headers: true).split("\n")
      expected = [
        'Content',
        'Truncated Content',
        'Created at',
        'Updated at',
        'Created Custom Label',
        'Updated at Custom Label'
      ].join(',')
      expect(header).to eq(expected)
    end

    it 'should not write headers if specified' do
      header, _foo = Array(@foo).to_comma(write_headers: false).split("\n")
      expected = [
        @content,
        @content[0..10],
        @time.to_formatted_s(:db),
        @time.to_formatted_s(:db),
        @time.to_formatted_s(:short),
        @time.to_formatted_s(:short)
      ].join(',')
      expect(header).to eq(expected)
    end
  end

  describe 'on an object with no comma declaration' do
    it 'should raise an error mentioning there is no comma description defined for that class' do
      expect { 'a string'.to_comma }.to raise_error('No comma format for class String defined for style default')
      expect { 'a string'.to_comma_headers }
        .to raise_error('No comma format for class String defined for style default')
    end
  end

  describe 'on objects using Single Table Inheritance' do
    before do
      class MySuperClass
        attr_accessor :content
        comma do; content end

        def initialize(content)
          @content = 'super-' + content
        end
      end

      class ChildClassComma < MySuperClass
        comma do; content end

        def initialize(content)
          @content = 'sub-' + content
        end
      end

      class ChildClassNoComma < MySuperClass
      end

      @childComma = ChildClassComma.new('content')
      @childNoComma = ChildClassNoComma.new('content')
    end

    it 'should return and array of data content, as defined in comma block in child class' do
      expect(@childComma.to_comma).to eq(%w[sub-content])
    end

    it 'should return and array of data content, as defined in comma block in super class, if not present in child' do
      expect(@childNoComma.to_comma).to eq(%w[super-content])
    end
  end
end

describe Comma, '__use__ keyword' do
  before(:all) do
    @obj = Class.new(Struct.new(:id, :title, :description)) do
      comma do
        title
        __use__ :description
      end

      comma :description do
        __use__ :static
        description
      end

      comma :static do
        __static_column__ do 'Foo, Inc.' end
      end
    end.new(1, 'Programming Ruby', 'The Pickaxe book')
  end

  subject { @obj.to_comma }
  its(:size) { should eq(3) }
  it { should eq(['Programming Ruby', 'Foo, Inc.', 'The Pickaxe book']) }
end


================================================
FILE: spec/comma/data_extractor_spec.rb
================================================
# frozen_string_literal: true

require 'spec_helper'

# comma do
#   name 'Title'
#   description
#
#   isbn :number_10 => 'ISBN-10', :number_13 => 'ISBN-13'
# end

describe Comma::DataExtractor do # rubocop:disable Metrics/BlockLength
  before do
    @isbn = Isbn.new('123123123', '321321321')
    @book = Book.new('Smalltalk-80', 'Language and Implementation', @isbn)

    @data = @book.to_comma
  end

  describe 'when no parameters are provided' do
    it 'should use the string value returned by sending the method name on the object' do
      expect(@data).to include('Language and Implementation')
    end
  end

  describe 'when given a string description as a parameter' do
    it 'should use the string value returned by sending the method name on the object' do
      expect(@data).to include('Smalltalk-80')
    end
  end

  describe 'when an hash is passed as a parameter' do
    describe 'with a string value' do
      it 'should use the string value, returned by sending the hash key to the object' do
        expect(@data).to include('123123123')
        expect(@data).to include('321321321')
      end

      it 'should not fail when an associated object is nil' do
        expect { Book.new('Smalltalk-80', 'Language and Implementation', nil).to_comma }.not_to raise_error
      end
    end
  end
end

describe Comma::DataExtractor, 'id attribute' do
  before do
    @data = Class.new(Struct.new(:id)) do
      comma do
        id 'ID' do |_id| '42' end
      end
    end.new(1).to_comma
  end

  it 'id attribute should yield block' do
    expect(@data).to include('42')
  end
end

describe Comma::DataExtractor, 'with static column method' do
  before do
    @data = Class.new(Struct.new(:id, :name)) do
      comma do
        __static_column__
        __static_column__ 'STATIC'
        __static_column__ 'STATIC' do '' end
        __static_column__ 'STATIC', &:name
      end
    end.new(1, 'John Doe').to_comma
  end

  it 'should extract headers' do
    expect(@data).to eq([nil, nil, '', 'John Doe'])
  end
end

describe Comma::DataExtractor, 'nil value' do
  before do
    @data = Class.new(Struct.new(:id, :name)) do
      comma do
        name
        name 'Name'
        name 'Name' do |_name| nil end
      end
    end.new(1, nil).to_comma
  end

  it 'should extract nil' do
    expect(@data).to eq([nil, nil, nil])
  end
end


================================================
FILE: spec/comma/header_extractor_spec.rb
================================================
# frozen_string_literal: true

require 'spec_helper'

# comma do
#   name 'Title'
#   description
#
#   isbn :number_10 => 'ISBN-10', :number_13 => 'ISBN-13'
# end

describe Comma::HeaderExtractor do # rubocop:disable Metrics/BlockLength
  before do
    @isbn = Isbn.new('123123123', '321321321')
    @book = Book.new('Smalltalk-80', 'Language and Implementation', @isbn)

    @headers = @book.to_comma_headers
  end

  describe 'when no parameters are provided' do
    it 'should use the method name as the header name, humanized' do
      expect(@headers).to include('Description')
    end
  end

  describe 'when given a string description as a parameter' do
    it 'should use the string value, unmodified' do
      expect(@headers).to include('Title')
    end
  end

  describe 'when an hash is passed as a parameter' do
    describe 'with a string value' do
      it 'should use the string value, unmodified' do
        expect(@headers).to include('ISBN-10')
      end
    end

    describe 'with a non-string value' do
      it 'should use the non string value converted to a string, humanized' do
        expect(@headers).to include('Issuer')
      end
    end
  end
end

describe Comma::HeaderExtractor, 'with static column method' do
  before do
    @headers = Class.new(Struct.new(:id, :name)) do
      comma do
        __static_column__
        __static_column__ 'STATIC'
        __static_column__ 'STATIC' do '' end
      end
    end.new(1, 'John Doe').to_comma_headers
  end

  it 'should extract headers' do
    expect(@headers).to eq(['', 'STATIC', 'STATIC'])
  end
end


================================================
FILE: spec/comma/rails/active_record_spec.rb
================================================
# frozen_string_literal: true

require 'spec_helper'

if defined? ActiveRecord

  describe Comma, 'generating CSV from an ActiveRecord object' do # rubocop:disable Metrics/BlockLength
    class Picture < ActiveRecord::Base
      belongs_to :imageable, polymorphic: true

      comma :pr_83 do
        imageable name: 'Picture'
      end
    end

    class Person < ActiveRecord::Base
      scope(:teenagers, -> { where(age: 13..19) })

      comma do
        name
        age
      end

      has_one :job

      comma :issue_75 do
        job :title
      end

      has_many :pictures, as: :imageable
    end

    class Job < ActiveRecord::Base
      belongs_to :person

      comma do
        person_formatter name: 'Name'
      end

      def person_formatter
        @person_formatter ||= PersonFormatter.new(person)
      end
    end

    class PersonFormatter
      def initialize(persor)
        @person = persor
      end

      def name
        @person.name
      end
    end

    before(:all) do
      # Setup AR model in memory
      ActiveRecord::Base.connection.create_table :pictures, force: true do |table|
        table.column :name, :string
        table.column :imageable_id, :integer
        table.column :imageable_type, :string
      end

      ActiveRecord::Base.connection.create_table :people, force: true do |table|
        table.column :name, :string
        table.column :age, :integer
      end
      Person.reset_column_information

      ActiveRecord::Base.connection.create_table :jobs, force: true do |table|
        table.column :person_id, :integer
        table.column :title, :string
      end
      Job.reset_column_information

      @person = Person.new(age: 18, name: 'Junior')
      @person.build_job(title: 'Nice job')
      @person.save!
      Picture.create(name: 'photo.jpg', imageable_id: @person.id, imageable_type: 'Person')
    end

    describe '#to_comma on scopes' do
      it 'should extend ActiveRecord::NamedScope::Scope to add a #to_comma method which will return CSV content for objects within the scope' do # rubocop:disable Layout/LineLength
        expect(Person.teenagers.to_comma).to eq "Name,Age\nJunior,18\n"
      end

      it 'should find in batches' do
        scope = Person.teenagers
        expect(scope).to receive(:find_each).and_yield @person
        scope.to_comma
      end

      it 'should fall back to iterating with each when scope has limit clause' do
        scope = Person.limit(1)
        expect(scope).to receive(:each).and_yield @person
        scope.to_comma
      end

      it 'should fall back to iterating with each when scope has order clause' do
        scope = Person.order(:age)
        expect(scope).to receive(:each).and_yield @person
        scope.to_comma
      end
    end

    describe 'with custom value_humanizer' do
      before do
        Comma::HeaderExtractor.value_humanizer =
          lambda do |value, model_class|
            if model_class.respond_to?(:human_attribute_name)
              model_class.human_attribute_name(value)
            else
              value.is_a?(String) ? value : value.to_s.humanize
            end
          end

        I18n.config.backend.store_translations(:ja, activerecord: { attributes: { person: { age: '年齢', name: '名前' } } })
        @original_locale = I18n.locale
        I18n.locale = :ja
      end

      after do
        I18n.locale = @original_locale

        Comma::HeaderExtractor.value_humanizer =
          Comma::HeaderExtractor::DEFAULT_VALUE_HUMANIZER
      end

      it 'should i18n-ize header values' do
        expect(Person.teenagers.to_comma).to match(/^名前,年齢/)
      end
    end

    describe 'github issue 75' do
      it 'should find association' do
        expect { Person.all.to_comma(:issue_75) }.not_to raise_error
      end
    end

    describe 'with accessor' do
      it 'should not raise exception' do
        expect(Job.all.to_comma).to eq("Name\nJunior\n")
      end
    end

    describe 'github pull-request 83' do
      it 'should not raise NameError' do
        expect { Picture.all.to_comma(:pr_83) }.not_to raise_error
      end
    end
  end

  describe Comma, 'generating CSV from an ActiveRecord object using Single Table Inheritance' do # rubocop:disable Metrics/BlockLength
    class Animal < ActiveRecord::Base
      comma do
        name 'Name' do |name|
          'Super-' + name
        end
      end

      comma :with_type do
        name
        type
      end
    end

    class Dog < Animal
      comma do
        name 'Name' do |name|
          'Dog-' + name
        end
      end
    end

    class Cat < Animal
    end

    before(:all) do
      # Setup AR model in memory
      ActiveRecord::Base.connection.create_table :animals, force: true do |table|
        table.column :name, :string
        table.column :type, :string
      end

      @dog = Dog.new(name: 'Rex')
      @dog.save!
      @cat = Cat.new(name: 'Kitty')
      @cat.save!
    end

    it 'should return and array of data content, as defined in comma block in child class' do
      expect(@dog.to_comma).to eq %w[Dog-Rex]
    end

    # FIXME: this one is failing - the comma block from Dog is executed instead of the one from the super class
    it 'should return and array of data content, as defined in comma block in super class, if not present in child' do
      expect(@cat.to_comma).to eq %w[Super-Kitty]
    end

    it 'should call definion in parent class' do
      expect { @dog.to_comma(:with_type) }.not_to raise_error
    end
  end
end


================================================
FILE: spec/comma/rails/data_mapper_collection_spec.rb
================================================
# frozen_string_literal: true

require 'spec_helper'

if defined? DataMapper

  describe Comma, 'generating CSV from an DataMapper object' do # rubocop:disable Metrics/BlockLength
    class Person
      include DataMapper::Resource

      property :id, Serial
      property :name, String
      property :age, Integer

      def self.teenagers
        all(:age.gte => 13) & all(:age.lte => 19)
      end

      comma do
        name
        age
      end
    end
    DataMapper.finalize

    before(:all) do
      DataMapper.setup(:default, 'sqlite::memory:')
      DataMapper.auto_migrate!
    end

    after(:all) do
    end

    describe 'case' do
      before do
        @person = Person.new(age: 18, name: 'Junior')
        @person.save
      end

      it 'should extend scope to add a #to_comma method which will return CSV content for objects within the scope' do
        Person.teenagers.to_comma.should == "Name,Age\nJunior,18\n"
      end

      it 'should find in batches' do
        Person.teenagers.to_comma
      end
    end
  end
end


================================================
FILE: spec/comma/rails/mongoid_spec.rb
================================================
# frozen_string_literal: true

require 'spec_helper'

if defined? Mongoid

  describe Comma, 'generating CSV from an Mongoid object' do
    class Person
      include Mongoid::Document

      field :name, type: String
      field :age, type: Integer

      scope :teenagers, between(age: 13..19)

      comma do
        name
        age
      end
    end

    after(:all) do
      Mongoid.purge!
    end

    describe 'case' do
      before do
        @person = Person.new(age: 18, name: 'Junior')
        @person.save
      end

      it 'should extend ActiveRecord::NamedScope::Scope to add a #to_comma method which will return CSV content for objects within the scope' do # rubocop:disable Layout/LineLength
        Person.teenagers.to_comma.should == "Name,Age\nJunior,18\n"
      end

      it 'should find in batches' do
        Person.teenagers.to_comma
      end
    end
  end
end


================================================
FILE: spec/controllers/users_controller_spec.rb
================================================
# frozen_string_literal: true

require 'spec_helper'

if defined?(Rails)

  RSpec.describe UsersController, type: :controller do # rubocop:disable Metrics/BlockLength
    describe 'rails setup' do
      it 'should capture the CSV renderer provided by Rails' do
        mock_users = [mock_model(User), mock_model(User)]
        allow(User).to receive(:all).and_return(mock_users)

        expect(mock_users).to receive(:to_comma).once

        get :index, format: :csv
      end
    end

    describe 'controller' do # rubocop:disable Metrics/BlockLength
      before(:all) do
        @user_1 = User.create!(first_name: 'Fred', last_name: 'Flintstone')
        @user_2 = User.create!(first_name: 'Wilma', last_name: 'Flintstone')
      end

      it 'should not affect html requested' do
        get :index

        expect(response.status).to eq 200
        expect(response.media_type).to eq 'text/html'
        expect(response.body).to eq 'Users!'
      end

      it 'should return a csv when requested' do
        get :index, format: :csv

        expect(response.status).to eq 200
        expect(response.media_type).to eq 'text/csv'
        expect(response.header['Content-Disposition']).to include('filename="data.csv"')

        expected_content = <<-CSV.gsub(/^\s+/, '')
        First name,Last name,Name
        Fred,Flintstone,Fred Flintstone
        Wilma,Flintstone,Wilma Flintstone
        CSV

        expect(response.body).to eq expected_content
      end

      describe 'with comma options' do
        it 'should allow the style to be chosen from the renderer' do
          # Must be passed in same format (string/symbol) eg:
          # format.csv  { render User.all, :style => :shortened }

          get :with_custom_style, format: :csv

          expected_content = <<-CSV.gsub(/^\s+/, '')
          First name,Last name
          Fred,Flintstone
          Wilma,Flintstone
          CSV

          expect(response.body).to eq expected_content
        end
      end

      describe 'with custom options' do # rubocop:disable Metrics/BlockLength
        def is_rails_4?
          Rails::VERSION::STRING =~ /^4.*/
        end

        def get_(name, **args)
          if is_rails_4? && args[:params]
            args.merge!(args[:params])
            args.delete(:params)
          end
          get name, **args
        end

        it 'should allow a filename to be set' do
          get_ :with_custom_options, format: :csv, params: { custom_options: { filename: 'my_custom_name' } }

          expect(response.status).to eq 200
          expect(response.media_type).to eq 'text/csv'
          expect(response.header['Content-Disposition']).to include('filename="my_custom_name.csv"')
        end

        it 'should allow a custom filename with spaces' do
          require 'shellwords'
          params = { custom_options: { filename: 'filename with a lot of spaces' } }
          get_ :with_custom_options, format: :csv, params: params

          expect(response.status).to eq 200
          expect(response.media_type).to eq 'text/csv'
          expect(response.header['Content-Disposition']).to include('filename="filename with a lot of spaces.csv"')

          filename_string = response.header['Content-Disposition'].split('=').last
          # shellsplit honors quoted strings
          expect(filename_string.shellsplit.length).to eq 1
        end

        it 'should allow a file extension to be set' do
          get_ :with_custom_options, format: :csv, params: { custom_options: { extension: :txt } }

          expect(response.status).to eq 200
          expect(response.media_type).to eq 'text/csv'
          expect(response.header['Content-Disposition']).to include('filename="data.txt"')
        end

        it 'should allow mime type to be set' do
          get_ :with_custom_options, format: :csv, params: { custom_options: { mime_type: 'text/plain' } }
          expect(response.status).to eq 200
          expect(response.media_type).to eq 'text/plain'
        end

        it 'should allow bom to be set' do
          get_ :with_custom_options, format: :csv, params: { custom_options: { with_bom: true } }

          expected_content = <<-CSV.gsub(/^\s+/, '')
          \xEF\xBB\xBFFirst name,Last name,Name
          Fred,Flintstone,Fred Flintstone
          Wilma,Flintstone,Wilma Flintstone
          CSV

          expect(response.body). to eq expected_content
        end

        describe 'headers' do
          it 'should allow toggling on' do
            get_ :with_custom_options, format: :csv, params: { custom_options: { write_headers: 'true' } }

            expect(response.status).to eq 200
            expect(response.media_type).to eq 'text/csv'

            expected_content = <<-CSV.gsub(/^\s+/, '')
            First name,Last name,Name
            Fred,Flintstone,Fred Flintstone
            Wilma,Flintstone,Wilma Flintstone
            CSV

            expect(response.body).to eq expected_content
          end

          it 'should allow toggling off' do
            get_ :with_custom_options, format: :csv, params: { custom_options: { write_headers: false } }

            expect(response.status).to eq 200
            expect(response.media_type).to eq 'text/csv'

            expected_content = <<-CSV.gsub(/^\s+/, '')
            Fred,Flintstone,Fred Flintstone
            Wilma,Flintstone,Wilma Flintstone
            CSV

            expect(response.body).to eq expected_content
          end
        end

        it 'should allow forcing of quotes' do
          get_ :with_custom_options, format: :csv, params: { custom_options: { force_quotes: true } }

          expect(response.status).to eq 200
          expect(response.media_type).to eq 'text/csv'

          expected_content = <<-CSV.gsub(/^\s+/, '')
          "First name","Last name","Name"
          "Fred","Flintstone","Fred Flintstone"
          "Wilma","Flintstone","Wilma Flintstone"
          CSV

          expect(response.body).to eq expected_content
        end

        it 'should allow combinations of options' do
          params = {
            custom_options: {
              write_headers: false,
              force_quotes: true,
              col_sep: '||',
              row_sep: "ENDOFLINE\n"
            }
          }
          get_ :with_custom_options, format: :csv, params: params

          expect(response.status).to eq 200
          expect(response.media_type).to eq 'text/csv'

          expected_content = <<-CSV.gsub(/^\s+/, '')
          "Fred"||"Flintstone"||"Fred Flintstone"ENDOFLINE
          "Wilma"||"Flintstone"||"Wilma Flintstone"ENDOFLINE
          CSV

          expect(response.body).to eq expected_content
        end
      end
    end
  end
end


================================================
FILE: spec/non_rails_app/ruby_classes.rb
================================================
# frozen_string_literal: true

class Book
  attr_accessor :name, :description, :isbn

  def initialize(name, description, isbn)
    @name = name
    @description = description
    @isbn = isbn
  end

  comma do
    name 'Title'
    description

    isbn authority: :issuer
    isbn number_10: 'ISBN-10'
    isbn number_13: 'ISBN-13'
  end

  comma :brief do
    name
    description
  end
end

class Isbn
  attr_accessor :number_10, :number_13

  def initialize(isbn_10, isbn_13)
    @number_10 = isbn_10
    @number_13 = isbn_13
  end

  def authority
    'ISBN'
  end
end


================================================
FILE: spec/rails_app/active_record/config.rb
================================================
# frozen_string_literal: true

ActiveRecord::Base.configurations = { 'test' => { 'adapter' => 'sqlite3', 'database' => ':memory:' } }
ActiveRecord::Base.establish_connection(:test)


================================================
FILE: spec/rails_app/active_record/models.rb
================================================
# frozen_string_literal: true

class Post < ActiveRecord::Base
  has_one :user

  comma do
    title
    description

    user :full_name
  end
end

class User < ActiveRecord::Base
  comma do
    first_name
    last_name
    full_name 'Name'
  end

  comma :shortened do
    first_name
    last_name
  end

  def full_name
    "#{first_name} #{last_name}".strip
  end
end

class CreateTables < ActiveRecord::Migration[4.2]
  def self.up
    create_table :users do |t|
      t.string      :first_name
      t.string      :last_name
      t.timestamps
    end

    create_table :posts do |t|
      t.references :user
      t.string :title
      t.string :description
      t.timestamps
    end
  end

  def self.down
    drop_table :posts
    drop_table :users
  end
end
ActiveRecord::Migration.verbose = false
CreateTables.up


================================================
FILE: spec/rails_app/data_mapper/config.rb
================================================
# frozen_string_literal: true

DataMapper.setup(:default, 'sqlite::memory:')


================================================
FILE: spec/rails_app/mongoid/config.rb
================================================
# frozen_string_literal: true

Mongoid.configure do |config|
  config.sessions = {
    default: {
      hosts: ['localhost:27017'], database: 'comma_test'
    }
  }
end


================================================
FILE: spec/rails_app/rails_app.rb
================================================
# frozen_string_literal: true

require 'action_controller/railtie'
require 'action_view/railtie'

# orm configs
require 'rails_app/active_record/config' if defined?(ActiveRecord)

app = CommaTestApp = Class.new(Rails::Application)
app.config.secret_token = '6f6acf0443f74fd0aa8ff07a7c2fbe0a'
app.config.session_store :cookie_store, key: '_rails_app_session'
app.config.active_support.deprecation = :log
app.config.eager_load = false
app.config.root = File.dirname(__FILE__)
Rails.backtrace_cleaner.remove_silencers!
app.initialize!

app.routes.draw do
  resources :users, only: [:index]
  get 'with_custom_options', to: 'users#with_custom_options'
  get 'with_custom_style', to: 'users#with_custom_style'
  root to: 'users#index'
end

# models
require 'rails_app/active_record/models' if defined?(ActiveRecord)

def is_rails_4?
  Rails::VERSION::STRING =~ /^4.*/
end

if is_rails_4?
  def symbolize_param_keys(params)
    params.symbolize_keys
  end
else
  def symbolize_param_keys(params)
    if params
      params.to_unsafe_h.symbolize_keys
    else
      {}
    end
  end
end

# controllers
class ApplicationController < ActionController::Base; end
class UsersController < ApplicationController
  def index
    respond_to do |format|
      format.html do
        if is_rails_4?
          render text: 'Users!'
        else
          render plain: 'Users!'
        end
      end
      format.csv  { render csv: User.all }
    end
  end

  def with_custom_options
    render_options = { csv: User.all }.update(symbolize_param_keys(params[:custom_options]))

    respond_to do |format|
      format.csv  { render render_options }
    end
  end

  def with_custom_style
    respond_to do |format|
      format.csv  { render csv: User.all, style: :shortened }
    end
  end
end

# helpers
Object.const_set(:ApplicationHelper, Module.new)


================================================
FILE: spec/rails_app/tmp/.gitkeep
================================================


================================================
FILE: spec/spec_helper.rb
================================================
# frozen_string_literal: true

require 'rubygems'
$LOAD_PATH.unshift(File.expand_path(File.join('..', '..', 'lib'), __FILE__))

require 'simplecov'
require 'coveralls'
SimpleCov.formatter = Coveralls::SimpleCov::Formatter
if defined? Rails
  SimpleCov.start('rails') do
    add_filter %r{^/spec/comma/rails/data_mapper_collection_spec\.rb$}
    add_filter %r{^/spec/comma/rails/mongoid_spec\.rb$}
  end
else
  SimpleCov.start do
    add_filter %r{^/spec/comma/rails/data_mapper_collection_spec\.rb}
    add_filter %r{^/spec/comma/rails/mongoid_spec\.rb}
    add_filter %r{^/spec/controllers/}
  end
end

require 'bundler/setup'
Bundler.require

require 'rspec/active_model/mocks'
require 'rspec/its'

begin
  require 'rails'
rescue LoadError
  warn 'rails not loaded'
end

%w[data_mapper mongoid active_record].each do |orm|
  begin
    require orm
    break
  rescue LoadError
    warn "#{orm} not loaded"
  end
end

if defined? Rails
  require 'rails_app/rails_app'
  require 'rspec/rails'
else
  require 'rails_app/data_mapper/config' if defined?(DataMapper)
  require 'rails_app/mongoid/config' if defined?(Mongoid)
  require 'rails_app/active_record/config' if defined?(ActiveRecord)
end

Dir[File.dirname(__FILE__) + '/support/**/*.rb'].each { |file| require file }

require File.expand_path('../spec/non_rails_app/ruby_classes', __dir__)
Download .txt
gitextract_uknkcqm5/

├── .coveralls.yml
├── .github/
│   └── workflows/
│       └── build.yml
├── .gitignore
├── .rspec
├── .rubocop.yml
├── .rubocop_todo.yml
├── .travis.yml
├── Appraisals
├── Gemfile
├── MIT-LICENSE
├── README.md
├── Rakefile
├── comma.gemspec
├── gemfiles/
│   ├── active6.0.6.gemfile
│   ├── active6.1.7.6.gemfile
│   ├── active7.0.8.gemfile
│   ├── active7.1.3.gemfile
│   ├── rails6.0.6.gemfile
│   ├── rails6.1.7.6.gemfile
│   ├── rails7.0.8.gemfile
│   └── rails7.1.3.gemfile
├── init.rb
├── lib/
│   ├── comma/
│   │   ├── array.rb
│   │   ├── data_extractor.rb
│   │   ├── data_mapper_collection.rb
│   │   ├── extractor.rb
│   │   ├── generator.rb
│   │   ├── header_extractor.rb
│   │   ├── mongoid.rb
│   │   ├── object.rb
│   │   ├── relation.rb
│   │   └── version.rb
│   └── comma.rb
└── spec/
    ├── comma/
    │   ├── comma_spec.rb
    │   ├── data_extractor_spec.rb
    │   ├── header_extractor_spec.rb
    │   └── rails/
    │       ├── active_record_spec.rb
    │       ├── data_mapper_collection_spec.rb
    │       └── mongoid_spec.rb
    ├── controllers/
    │   └── users_controller_spec.rb
    ├── non_rails_app/
    │   └── ruby_classes.rb
    ├── rails_app/
    │   ├── active_record/
    │   │   ├── config.rb
    │   │   └── models.rb
    │   ├── data_mapper/
    │   │   └── config.rb
    │   ├── mongoid/
    │   │   └── config.rb
    │   ├── rails_app.rb
    │   └── tmp/
    │       └── .gitkeep
    └── spec_helper.rb
Download .txt
SYMBOL INDEX (98 symbols across 19 files)

FILE: lib/comma.rb
  type Comma (line 6) | module Comma

FILE: lib/comma/array.rb
  class Array (line 3) | class Array
    method to_comma (line 4) | def to_comma(style = :default)

FILE: lib/comma/data_extractor.rb
  type Comma (line 5) | module Comma
    class DataExtractor (line 6) | class DataExtractor < Extractor
      class ExtractValueFromInstance (line 7) | class ExtractValueFromInstance
        method initialize (line 8) | def initialize(instance)
        method extract (line 12) | def extract(sym, &block)
        method yield_block_with_value (line 18) | def yield_block_with_value(value, &block)
        method extract_value (line 22) | def extract_value(method)
        method extraction_object (line 26) | def extraction_object
      class ExtractValueFromAssociationOfInstance (line 31) | class ExtractValueFromAssociationOfInstance < ExtractValueFromInstance
        method initialize (line 32) | def initialize(instance, association_name)
        method extraction_object (line 39) | def extraction_object
        method null_association (line 43) | def null_association
      method method_missing (line 52) | def method_missing(sym, *args, &block)
      method __static_column__ (line 72) | def __static_column__(_header = nil, &block)

FILE: lib/comma/data_mapper_collection.rb
  type DataMapper (line 4) | module DataMapper
    class Collection (line 5) | class Collection
      method to_comma (line 6) | def to_comma(style = :default)

FILE: lib/comma/extractor.rb
  type Comma (line 3) | module Comma
    class Extractor (line 4) | class Extractor
      method initialize (line 5) | def initialize(instance, style, formats)
      method results (line 12) | def results
      method id (line 17) | def id(*args, &block)
      method __use__ (line 21) | def __use__(style)
      method convert_to_data_value (line 28) | def convert_to_data_value(result)

FILE: lib/comma/generator.rb
  type Comma (line 3) | module Comma
    class Generator (line 4) | class Generator
      method initialize (line 5) | def initialize(instance, style)
      method run (line 17) | def run(iterator_method)
      method append_csv (line 27) | def append_csv(csv, iterator_method)

FILE: lib/comma/header_extractor.rb
  type Comma (line 10) | module Comma
    class HeaderExtractor (line 11) | class HeaderExtractor < Extractor
      method method_missing (line 19) | def method_missing(sym, *args, &_block)
      method __static_column__ (line 38) | def __static_column__(header = '', &_block)
      method get_association_class (line 44) | def get_association_class(model_class, association)

FILE: lib/comma/mongoid.rb
  type Mongoid (line 7) | module Mongoid
    class Criteria (line 8) | class Criteria
      method to_comma (line 9) | def to_comma(style = :default)

FILE: lib/comma/object.rb
  class Object (line 6) | class Object
    method comma (line 10) | def comma(style = :default, &block)
    method inherited (line 14) | def inherited(subclass)
    method to_comma (line 20) | def to_comma(style = :default)
    method to_comma_headers (line 24) | def to_comma_headers(style = :default)
    method extract_with (line 30) | def extract_with(extractor_class, style = :default)
    method raise_unless_style_exists (line 35) | def raise_unless_style_exists(style)

FILE: lib/comma/relation.rb
  type ActiveRecord (line 3) | module ActiveRecord
    class Relation (line 4) | class Relation
      method to_comma (line 5) | def to_comma(style = :default)

FILE: lib/comma/version.rb
  type Comma (line 3) | module Comma

FILE: spec/comma/comma_spec.rb
  class Foo (line 92) | class Foo
    method initialize (line 126) | def initialize(content)
    method initialize (line 153) | def initialize(content)
    method initialize (line 193) | def initialize(content, created_at = Time.now, updated_at = Time.now)
  class Bar (line 105) | class Bar
  class Foo (line 122) | class Foo
    method initialize (line 126) | def initialize(content)
    method initialize (line 153) | def initialize(content)
    method initialize (line 193) | def initialize(content, created_at = Time.now, updated_at = Time.now)
  class Foo (line 149) | class Foo
    method initialize (line 126) | def initialize(content)
    method initialize (line 153) | def initialize(content)
    method initialize (line 193) | def initialize(content, created_at = Time.now, updated_at = Time.now)
  class Foo (line 182) | class Foo
    method initialize (line 126) | def initialize(content)
    method initialize (line 153) | def initialize(content)
    method initialize (line 193) | def initialize(content, created_at = Time.now, updated_at = Time.now)
  class MySuperClass (line 268) | class MySuperClass
    method initialize (line 272) | def initialize(content)
  class ChildClassComma (line 277) | class ChildClassComma < MySuperClass
    method initialize (line 280) | def initialize(content)
  class ChildClassNoComma (line 285) | class ChildClassNoComma < MySuperClass

FILE: spec/comma/rails/active_record_spec.rb
  class Picture (line 8) | class Picture < ActiveRecord::Base
  class Person (line 16) | class Person < ActiveRecord::Base
  class Job (line 33) | class Job < ActiveRecord::Base
    method person_formatter (line 40) | def person_formatter
  class PersonFormatter (line 45) | class PersonFormatter
    method initialize (line 46) | def initialize(persor)
    method name (line 50) | def name
  class Animal (line 153) | class Animal < ActiveRecord::Base
  class Dog (line 166) | class Dog < Animal
  class Cat (line 174) | class Cat < Animal

FILE: spec/comma/rails/data_mapper_collection_spec.rb
  class Person (line 8) | class Person
    method teenagers (line 15) | def self.teenagers

FILE: spec/comma/rails/mongoid_spec.rb
  class Person (line 8) | class Person

FILE: spec/controllers/users_controller_spec.rb
  function is_rails_4? (line 67) | def is_rails_4?
  function get_ (line 71) | def get_(name, **args)

FILE: spec/non_rails_app/ruby_classes.rb
  class Book (line 3) | class Book
    method initialize (line 6) | def initialize(name, description, isbn)
  class Isbn (line 27) | class Isbn
    method initialize (line 30) | def initialize(isbn_10, isbn_13)
    method authority (line 35) | def authority

FILE: spec/rails_app/active_record/models.rb
  class Post (line 3) | class Post < ActiveRecord::Base
  class User (line 14) | class User < ActiveRecord::Base
    method full_name (line 26) | def full_name
  class CreateTables (line 31) | class CreateTables < ActiveRecord::Migration[4.2]
    method up (line 32) | def self.up
    method down (line 47) | def self.down

FILE: spec/rails_app/rails_app.rb
  function is_rails_4? (line 28) | def is_rails_4?
  function symbolize_param_keys (line 33) | def symbolize_param_keys(params)
  function symbolize_param_keys (line 37) | def symbolize_param_keys(params)
  class ApplicationController (line 47) | class ApplicationController < ActionController::Base; end
  class UsersController (line 48) | class UsersController < ApplicationController
    method index (line 49) | def index
    method with_custom_options (line 62) | def with_custom_options
    method with_custom_style (line 70) | def with_custom_style
Condensed preview — 48 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (62K chars).
[
  {
    "path": ".coveralls.yml",
    "chars": 24,
    "preview": "service_name: travis-ci\n"
  },
  {
    "path": ".github/workflows/build.yml",
    "chars": 831,
    "preview": "name: Build\non: [push, pull_request]\njobs:\n  build:\n    strategy:\n      matrix:\n        ruby: ['3.0', '3.1', '3.2', '3.3"
  },
  {
    "path": ".gitignore",
    "chars": 106,
    "preview": "pkg/*\n.*.swp\n*~\n.bundle\nspec/rails_app/log\nspec/rails_app/db/development.sqlite*\n.rbx/\n.ruby-*\ncoverage/*\n"
  },
  {
    "path": ".rspec",
    "chars": 9,
    "preview": "--colour\n"
  },
  {
    "path": ".rubocop.yml",
    "chars": 352,
    "preview": "inherit_from: .rubocop_todo.yml\n\nrequire: rubocop-performance\n\nAllCops:\n  DisplayCopNames: true\n  Exclude:\n    - 'gemfil"
  },
  {
    "path": ".rubocop_todo.yml",
    "chars": 4536,
    "preview": "# This configuration was generated by\n# `rubocop --auto-gen-config`\n# on 2024-01-20 09:02:51 UTC using RuboCop version 1"
  },
  {
    "path": ".travis.yml",
    "chars": 1081,
    "preview": "sudo: false\n\nservices: mongodb\n\nlanguage: ruby\ncache: bundler\nrvm:\n  - 2.4.10\n  - 2.5.8\n  - 2.6.6\n  - 2.7.2\ngemfile:\n  -"
  },
  {
    "path": "Appraisals",
    "chars": 736,
    "preview": "# frozen_string_literal: true\n\nappraise 'rails6.0.6' do\n  gem 'rails', '6.0.6'\n  gem 'rspec-rails'\n  gem 'test-unit'\nend"
  },
  {
    "path": "Gemfile",
    "chars": 202,
    "preview": "# frozen_string_literal: true\n\nsource 'https://rubygems.org'\n\ngemspec\n\ngem 'coveralls', require: false\ngem 'rubocop', '~"
  },
  {
    "path": "MIT-LICENSE",
    "chars": 1058,
    "preview": "Copyright (c) 2009 Marcus Crafter\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this "
  },
  {
    "path": "README.md",
    "chars": 1738,
    "preview": "# Comma\n\nA library to generate comma seperated value (CSV) for Ruby objects like ActiveRecord and Array\n\n[![Gem Version]"
  },
  {
    "path": "Rakefile",
    "chars": 281,
    "preview": "# frozen_string_literal: true\n\nrequire 'bundler/setup'\nrequire 'bundler/gem_tasks'\n\nrequire 'rspec/core/rake_task'\nRSpec"
  },
  {
    "path": "comma.gemspec",
    "chars": 1041,
    "preview": "# frozen_string_literal: true\n\n$LOAD_PATH.push File.expand_path('lib', __dir__)\nrequire 'comma/version'\n\nGem::Specificat"
  },
  {
    "path": "gemfiles/active6.0.6.gemfile",
    "chars": 292,
    "preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"coveralls\", :require => false\ngem \"rubocop\","
  },
  {
    "path": "gemfiles/active6.1.7.6.gemfile",
    "chars": 296,
    "preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"coveralls\", :require => false\ngem \"rubocop\","
  },
  {
    "path": "gemfiles/active7.0.8.gemfile",
    "chars": 292,
    "preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"coveralls\", :require => false\ngem \"rubocop\","
  },
  {
    "path": "gemfiles/active7.1.3.gemfile",
    "chars": 292,
    "preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"coveralls\", :require => false\ngem \"rubocop\","
  },
  {
    "path": "gemfiles/rails6.0.6.gemfile",
    "chars": 290,
    "preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"coveralls\", :require => false\ngem \"rubocop\","
  },
  {
    "path": "gemfiles/rails6.1.7.6.gemfile",
    "chars": 292,
    "preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"coveralls\", :require => false\ngem \"rubocop\","
  },
  {
    "path": "gemfiles/rails7.0.8.gemfile",
    "chars": 274,
    "preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"coveralls\", :require => false\ngem \"rubocop\","
  },
  {
    "path": "gemfiles/rails7.1.3.gemfile",
    "chars": 274,
    "preview": "# This file was generated by Appraisal\n\nsource \"https://rubygems.org\"\n\ngem \"coveralls\", :require => false\ngem \"rubocop\","
  },
  {
    "path": "init.rb",
    "chars": 47,
    "preview": "# frozen_string_literal: true\n\nrequire 'comma'\n"
  },
  {
    "path": "lib/comma/array.rb",
    "chars": 135,
    "preview": "# frozen_string_literal: true\n\nclass Array\n  def to_comma(style = :default)\n    Comma::Generator.new(self, style).run(:e"
  },
  {
    "path": "lib/comma/data_extractor.rb",
    "chars": 1933,
    "preview": "# frozen_string_literal: true\n\nrequire 'comma/extractor'\n\nmodule Comma\n  class DataExtractor < Extractor\n    class Extra"
  },
  {
    "path": "lib/comma/data_mapper_collection.rb",
    "chars": 214,
    "preview": "# frozen_string_literal: true\n\nif defined?(DataMapper)\n  module DataMapper\n    class Collection\n      def to_comma(style"
  },
  {
    "path": "lib/comma/extractor.rb",
    "chars": 622,
    "preview": "# frozen_string_literal: true\n\nmodule Comma\n  class Extractor\n    def initialize(instance, style, formats)\n      @instan"
  },
  {
    "path": "lib/comma/generator.rb",
    "chars": 1031,
    "preview": "# frozen_string_literal: true\n\nmodule Comma\n  class Generator\n    def initialize(instance, style)\n      @instance = inst"
  },
  {
    "path": "lib/comma/header_extractor.rb",
    "chars": 1614,
    "preview": "# frozen_string_literal: true\n\nrequire 'comma/extractor'\nrequire 'active_support'\nrequire 'active_support/core_ext/class"
  },
  {
    "path": "lib/comma/mongoid.rb",
    "chars": 327,
    "preview": "# frozen_string_literal: true\n\n# Conditionally set to_comma on Mongoid records if mongoid gem is installed\nbegin\n  requi"
  },
  {
    "path": "lib/comma/object.rb",
    "chars": 939,
    "preview": "# frozen_string_literal: true\n\nrequire 'comma/data_extractor'\nrequire 'comma/header_extractor'\n\nclass Object\n  class_att"
  },
  {
    "path": "lib/comma/relation.rb",
    "chars": 547,
    "preview": "# frozen_string_literal: true\n\nmodule ActiveRecord\n  class Relation\n    def to_comma(style = :default)\n      iterator_me"
  },
  {
    "path": "lib/comma/version.rb",
    "chars": 68,
    "preview": "# frozen_string_literal: true\n\nmodule Comma\n  VERSION = '4.8.0'\nend\n"
  },
  {
    "path": "lib/comma.rb",
    "chars": 1821,
    "preview": "# frozen_string_literal: true\n\nrequire 'csv'\nCSV_HANDLER = CSV\n\nmodule Comma\n  DEFAULT_OPTIONS = {\n    write_headers: tr"
  },
  {
    "path": "spec/comma/comma_spec.rb",
    "chars": 10343,
    "preview": "# frozen_string_literal: true\n\nrequire File.dirname(__FILE__) + '/../spec_helper'\n\ndescribe Comma do\n  it 'should extend"
  },
  {
    "path": "spec/comma/data_extractor_spec.rb",
    "chars": 2357,
    "preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\n# comma do\n#   name 'Title'\n#   description\n#\n#   isbn :number_10 "
  },
  {
    "path": "spec/comma/header_extractor_spec.rb",
    "chars": 1586,
    "preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\n# comma do\n#   name 'Title'\n#   description\n#\n#   isbn :number_10 "
  },
  {
    "path": "spec/comma/rails/active_record_spec.rb",
    "chars": 5524,
    "preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nif defined? ActiveRecord\n\n  describe Comma, 'generating CSV from a"
  },
  {
    "path": "spec/comma/rails/data_mapper_collection_spec.rb",
    "chars": 1050,
    "preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nif defined? DataMapper\n\n  describe Comma, 'generating CSV from an "
  },
  {
    "path": "spec/comma/rails/mongoid_spec.rb",
    "chars": 889,
    "preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nif defined? Mongoid\n\n  describe Comma, 'generating CSV from an Mon"
  },
  {
    "path": "spec/controllers/users_controller_spec.rb",
    "chars": 6719,
    "preview": "# frozen_string_literal: true\n\nrequire 'spec_helper'\n\nif defined?(Rails)\n\n  RSpec.describe UsersController, type: :contr"
  },
  {
    "path": "spec/non_rails_app/ruby_classes.rb",
    "chars": 574,
    "preview": "# frozen_string_literal: true\n\nclass Book\n  attr_accessor :name, :description, :isbn\n\n  def initialize(name, description"
  },
  {
    "path": "spec/rails_app/active_record/config.rb",
    "chars": 181,
    "preview": "# frozen_string_literal: true\n\nActiveRecord::Base.configurations = { 'test' => { 'adapter' => 'sqlite3', 'database' => '"
  },
  {
    "path": "spec/rails_app/active_record/models.rb",
    "chars": 825,
    "preview": "# frozen_string_literal: true\n\nclass Post < ActiveRecord::Base\n  has_one :user\n\n  comma do\n    title\n    description\n\n  "
  },
  {
    "path": "spec/rails_app/data_mapper/config.rb",
    "chars": 77,
    "preview": "# frozen_string_literal: true\n\nDataMapper.setup(:default, 'sqlite::memory:')\n"
  },
  {
    "path": "spec/rails_app/mongoid/config.rb",
    "chars": 169,
    "preview": "# frozen_string_literal: true\n\nMongoid.configure do |config|\n  config.sessions = {\n    default: {\n      hosts: ['localho"
  },
  {
    "path": "spec/rails_app/rails_app.rb",
    "chars": 1837,
    "preview": "# frozen_string_literal: true\n\nrequire 'action_controller/railtie'\nrequire 'action_view/railtie'\n\n# orm configs\nrequire "
  },
  {
    "path": "spec/rails_app/tmp/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "spec/spec_helper.rb",
    "chars": 1345,
    "preview": "# frozen_string_literal: true\n\nrequire 'rubygems'\n$LOAD_PATH.unshift(File.expand_path(File.join('..', '..', 'lib'), __FI"
  }
]

About this extraction

This page contains the full source code of the comma-csv/comma GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 48 files (55.7 KB), approximately 16.7k tokens, and a symbol index with 98 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!