Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# Copilot instructions for `comma`

## Build, test, and lint commands

This repository is a Ruby gem. Ruby 3.0+ is required, and the CI matrix exercises Ruby 3.0-3.4 against Rails/ActiveRecord appraisals from 6.0 through 7.1.

```sh
# install dependencies for the base Gemfile
bundle install

# install all appraisal Gemfiles used by CI
bundle exec appraisal install

# build the gem
bundle exec rake build

# lint
bundle exec rubocop -P
# or
bundle exec rake rubocop

# base test suite (runs non-Rails specs when framework gems are absent)
bundle exec rspec spec
# or
bundle exec rake spec

# run one example from the base suite
bundle exec rspec spec/comma/comma_spec.rb:205

# run the full multi-gemfile matrix locally
bundle exec appraisal rake spec

# run a single spec file under a specific appraisal
bundle exec appraisal active7.1.3 bundle exec rspec spec/comma/rails/active_record_spec.rb

# CI equivalent for a single matrix entry
BUNDLE_GEMFILE=gemfiles/rails7.1.3.gemfile bundle exec rspec spec/controllers/users_controller_spec.rb
```

## High-level architecture

- `lib/comma/object.rb` adds the core DSL globally via `Object.comma`. Each class stores named format blocks in `comma_formats`, and subclasses inherit a shallow copy of those formats.
- `lib/comma/extractor.rb` is the shared execution engine. It `instance_eval`s a stored format block and collects stringified results. The two concrete extractors split responsibilities:
- `lib/comma/data_extractor.rb` resolves values from the instance or an associated object and applies optional block-based transformations.
- `lib/comma/header_extractor.rb` derives headers from the same DSL and can map association columns to the associated model class for humanized labels.
- `lib/comma/generator.rb` is the only place that turns object rows into CSV output. `Array`, `ActiveRecord::Relation`, `Mongoid::Criteria`, and `DataMapper::Collection` each delegate to it from their own extension files.
- `lib/comma.rb` wires framework integrations lazily with `ActiveSupport.on_load`. That file is also where the Rails `render csv:` renderer is registered, so controller behavior is part of the gem's load path rather than test-only glue.
- Integration specs use the miniature app under `spec/rails_app/` plus inline model definitions inside spec files. The base suite still runs without Rails, Mongoid, DataMapper, or ActiveRecord because integration examples are wrapped in `if defined?(...)` guards in the specs.

## Key conventions

- The CSV DSL is method-call driven. Inside a `comma` block, a bare method adds one column, a string argument overrides the header label, and symbol/hash arguments traverse associations. The same block definition drives both headers and row data.
- Style composition uses `__use__ :style_name`, and computed/static columns use `__static_column__`. Preserve those internal DSL entry points when changing extractor behavior.
- Header labels default to `HeaderExtractor.value_humanizer`, which is mutable global state. Specs that override it reset it afterward; follow the same pattern for any future changes.
- `ActiveRecord::Relation#to_comma` intentionally uses `find_each` only for unordered, unlimited relations. If a relation has `limit` or `order`, it falls back to `each`; when Rails is loaded it also emits a warning instead of forcing batched iteration.
- Specs commonly define throwaway classes inline to document DSL behavior instead of introducing fixtures or helper classes. Prefer extending the existing focused examples in `spec/comma/*` unless a change genuinely needs the Rails test app.
98 changes: 89 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# Comma

A library to generate comma seperated value (CSV) for Ruby objects like ActiveRecord and Array
A library for generating comma-separated values (CSV) from Ruby objects, arrays, and supported ORM collections.

[![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.
You need Ruby 3.0 or later.

For Rails / ActiveRecord integration, this repository is currently tested against ActiveRecord and Rails 6.0 through 7.1 on Ruby 3.0 through 3.4.

### Installing

Expand All @@ -17,33 +19,111 @@ Comma is distributed as a gem, best installed via Bundler.
Include the gem in your Gemfile:

```ruby
gem 'comma', '~> 4.8.0'
gem 'comma', '~> 4.9.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'
gem 'comma', git: 'https://github.com/comma-csv/comma.git'
```

Then, run `bundle install`.

### Usage

See [this page](https://github.com/comma-csv/comma/wiki) for usages.
Define a CSV format on your object with `comma`. Calling `to_comma` on a single object returns the row values, while calling it on an array or supported collection generates CSV output:

```ruby
class User
attr_reader :first_name, :last_name

def initialize(first_name, last_name)
@first_name = first_name
@last_name = last_name
end

comma do
first_name
last_name
full_name 'Name'
end

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

user = User.new('Ada', 'Lovelace')
user.to_comma
# => ["Ada", "Lovelace", "Ada Lovelace"]

users = [User.new('Ada', 'Lovelace'), User.new('Grace', 'Hopper')]
users.to_comma
# => "First name,Last name,Name\nAda,Lovelace,Ada Lovelace\nGrace,Hopper,Grace Hopper\n"
```

You can also define named styles and select them when generating CSV:

```ruby
class User
comma :short do
first_name
last_name
end
end

users.to_comma(:short)
```

In Rails controllers, requiring the gem registers `render csv:` support:

```ruby
def index
render csv: User.all
end
```

See the [wiki](https://github.com/comma-csv/comma/wiki) for more usage examples.

## 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:
Install dependencies:

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

Run the default test suite and linter:

```sh
bundle exec rspec spec
bundle exec rubocop -P
```

Run a single example:

```sh
bundle exec rspec spec/comma/comma_spec.rb:205
```

To run the test suite across the Rails / ActiveRecord gemfile matrix, this repository uses [Appraisal](https://github.com/thoughtbot/appraisal):

```sh
bundle exec appraisal rake spec
```

You can also run a specific spec under one appraisal:

```sh
bundle exec appraisal rails7.1.3 bundle exec rspec spec/controllers/users_controller_spec.rb
```

## Contributing

Please make sure `bundle exec rspec spec`, `bundle exec rubocop -P`, and any relevant `bundle exec appraisal ...` commands pass before opening a pull request.

## 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).
Expand All @@ -56,4 +136,4 @@ We use [SemVer](http://semver.org/) for versioning. For the versions available,

## 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.
This project is licensed under the MIT License - see the [MIT-LICENSE](https://github.com/comma-csv/comma/blob/master/MIT-LICENSE) file for details.
Loading