<commit_before># RecordCollection
[<img src="https://secure.travis-ci.org/bterkuile/record_collection.png?branch=master" alt="Build Status" />](http://travis-ci.org/bterkuile/record_collection)

record\_collection is a gem that adds functionality to rails to work
with collections. This consists of a few components:

* Collection objects containing some active record models and acting on
  that collection.
* the multi\_select helpers for selecting records from the index page
* the optionals helpers for managing attributes on the collection of
  records you may or may not want to edit in the collection form

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'record_collection'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install record_collection

## Adding routes
Add two collection routes to the normal resources definition.
This call behaves exactly as the normal resources :... call,
but adds:
```ruby
 collection do
   get :collection_edit
   post :collection_update
 end
```
So the route definition in `config/routes.rb` defined as:
```ruby
  collection_resources :employees, except: [:new]
```
is exactly the same as:
```ruby
  resources :employees, except: [:new] do
    collection do
      get :collection_edit
      post :collection_update
    end
  end
```

## Defining the collection
A good practice is to define your collection as a subclass of your
resource class. So an employees collection should be defined like:
`app/models/employee.rb`:
```ruby
class Employee < ActiveRecord::Base
  # attribute :admin, type: Boolean (defined by database)
  validates :name, presence: true

end
```
`app/models/employee/collection.rb`:
```ruby
class Employee::Collection < RecordCollection::Base
  attribute :name
  validates :section, format: {with: /\A\w{3}\Z/, if: 'section.present?' }
  attribute :admin, type: Boolean
  attribute :vegan, type: Boolean
end
```
See the [active_attr](https://github.com/cgriego/active_attr) gem for
attribute definitions.

## Defining your controllers
If you already used the specification `collection_resources :employees` in
your [config/routes.rb](spec/dummy/config/routes.rb) file you can add
the actions in your controller typically looking like:
```ruby
class EmployeesController < ApplicationController
  # your standard actions here

  # GET /employees/collection_edit?ids[]=1&ids[]=3&...
  def collection_edit
    @collection = Employee::Collection.find(params[:ids])
    redirect_to employees_path, alert: 'No employees selected' if @collection.empty?
  end

  # POST /employees/collection_update
  def collection_update
    @collection = Employee::Collection.find(params[:ids])
    if @collection.update params[:collection]
      redirect_to employees_path, notice: 'Collection is updated'
    else
      render 'collection_edit'
    end
  end  
end
```
For more advanced use of the collection the pattern above can of course
be different eg: different collection objects for the same active record
model types.

## Creating your views
The
[app/views/employess/collection_edit.html.slim](spec/dummy/app/views/employees/collection_edit.html.slim) view is a tricky one.
Since we are working on a collection of record, and want to edit those
attributes we just want a normal form for editing the attributes,
treating the collection as the record itself. The problem however is
that some attributes can be in a mixed state, say two employees, one
having `admin => true`, the other one `admin => false`. If I only want
to update the section they are both in, I want to leave the admin
attribute allone. To accomplish this, this gem provides the `optional`
helpers. These helpers make it easy to manage a form of attributes where
you can determine which attributes you want to manage for this
particular collection of records. This gem also support [simple_form](https://github.com/plataformatec/simple_form)
gem where you can replace `f.input :attribute, ...etc` with
`f.optional_input :attribute, ...etc`. Our current example works with
the standard [form_helpers](http://guides.rubyonrails.org/form_helpers.html)<br>
### currently supported helpers:
* `optional_boolean`
* `optional_text_field`
* `optional_input` ([simple_form](https://github.com/plataformatec/simple_form))

The form you create typically looks like [app/views/employees/collection_edit.html.slim](spec/dummy/app/views/employees/collection_edit.html.slim):
```slim
h1 Edit multiple employees
= form_for @collection, url: [:collection_update, @collection.record_class] do |f|
  = f.collection_ids
  .form-inputs= f.optional_text_field :section
  .form-inputs= f.optional_boolean :admin
  .form-inputs= f.optional_boolean :vegan
  .form-actions= f.submit
.page-actions
  = link_to 'Back', employees_path
```

That is the view part. Be sure to read the optionals section for a
better understanding of how the optional fields work.

## Selecting records from the index using checkboxes (multi_select)
The idea behind working with collections is that you end up as a `GET` request at:
`+controller+/collection_edit?ids[]=2&ids[]=3` etc. How you achieve this
is totally up to yourself, but this gem provides you with a nice
standard way of selecting records from the index page. To filter records
to a specific subset the [ransack](https://github.com/activerecord-hackery/ransack)
gem also provides a nice way to add filtering to the index page. To add
checkbox selecting to your page this gem assumes the following
structure using the [Slim lang](http://slim-lang.com/):
```slim
table.with-selection
  thead
    tr
      th Name
      th Section
  tbody
    - @employees.each do |employee|
      tr data-record=employee.attributes.to_json
```
Note that each row needs a json version of the record at least
containing its id.<br>
Implement the multiselect dependencies in your manifest files, typically
being `app/assets/javascripts/application.js`:
```javascript
//= require record_collection/multi_select
```
And for the styling provided by this gem ([app/assets/stylesheets/application.css](spec/dummy/app/assets/stylesheets/application.css.sass)):
```css
/*
 *= require record_collection/multi_select
 */
```<commit_msg>Clarify index action in README<commit_after># RecordCollection
[<img src="https://secure.travis-ci.org/bterkuile/record_collection.png?branch=master" alt="Build Status" />](http://travis-ci.org/bterkuile/record_collection)

record\_collection is a gem that adds functionality to rails to work
with collections. This consists of a few components:

* Collection objects containing some active record models and acting on
  that collection.
* the multi\_select helpers for selecting records from the index page
* the optionals helpers for managing attributes on the collection of
  records you may or may not want to edit in the collection form

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'record_collection'
```

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install record_collection

## Adding routes
Add two collection routes to the normal resources definition.
This call behaves exactly as the normal resources :... call,
but adds:
```ruby
 collection do
   get :collection_edit
   post :collection_update
 end
```
So the route definition in `config/routes.rb` defined as:
```ruby
  collection_resources :employees, except: [:new]
```
is exactly the same as:
```ruby
  resources :employees, except: [:new] do
    collection do
      get :collection_edit
      post :collection_update
    end
  end
```

## Defining the collection
A good practice is to define your collection as a subclass of your
resource class. So an employees collection should be defined like:
`app/models/employee.rb`:
```ruby
class Employee < ActiveRecord::Base
  # attribute :admin, type: Boolean (defined by database)
  validates :name, presence: true

end
```
`app/models/employee/collection.rb`:
```ruby
class Employee::Collection < RecordCollection::Base
  attribute :name
  validates :section, format: {with: /\A\w{3}\Z/, if: 'section.present?' }
  attribute :admin, type: Boolean
  attribute :vegan, type: Boolean
end
```
See the [active_attr](https://github.com/cgriego/active_attr) gem for
attribute definitions.

## Defining your controllers
If you already used the specification `collection_resources :employees` in
your [config/routes.rb](spec/dummy/config/routes.rb) file you can add
the actions in your controller typically looking like:
```ruby
class EmployeesController < ApplicationController
  # your standard actions here

  # GET /employees/collection_edit?ids[]=1&ids[]=3&...
  def collection_edit
    @collection = Employee::Collection.find(params[:ids])
    redirect_to employees_path, alert: 'No employees selected' if @collection.empty?
  end

  # POST /employees/collection_update
  def collection_update
    @collection = Employee::Collection.find(params[:ids])
    if @collection.update params[:collection]
      redirect_to employees_path, notice: 'Collection is updated'
    else
      render 'collection_edit'
    end
  end  
end
```
For more advanced use of the collection the pattern above can of course
be different eg: different collection objects for the same active record
model types.

## Creating your views
The
[app/views/employess/collection_edit.html.slim](spec/dummy/app/views/employees/collection_edit.html.slim) view is a tricky one.
Since we are working on a collection of record, and want to edit those
attributes we just want a normal form for editing the attributes,
treating the collection as the record itself. The problem however is
that some attributes can be in a mixed state, say two employees, one
having `admin => true`, the other one `admin => false`. If I only want
to update the section they are both in, I want to leave the admin
attribute allone. To accomplish this, this gem provides the `optional`
helpers. These helpers make it easy to manage a form of attributes where
you can determine which attributes you want to manage for this
particular collection of records. This gem also support [simple_form](https://github.com/plataformatec/simple_form)
gem where you can replace `f.input :attribute, ...etc` with
`f.optional_input :attribute, ...etc`. Our current example works with
the standard [form_helpers](http://guides.rubyonrails.org/form_helpers.html)<br>
### currently supported helpers:
* `optional_boolean`
* `optional_text_field`
* `optional_input` ([simple_form](https://github.com/plataformatec/simple_form))

The form you create typically looks like [app/views/employees/collection_edit.html.slim](spec/dummy/app/views/employees/collection_edit.html.slim):
```slim
h1 Edit multiple employees
= form_for @collection, url: [:collection_update, @collection.record_class] do |f|
  = f.collection_ids
  .form-inputs= f.optional_text_field :section
  .form-inputs= f.optional_boolean :admin
  .form-inputs= f.optional_boolean :vegan
  .form-actions= f.submit
.page-actions
  = link_to 'Back', employees_path
```

That is the view part. Be sure to read the optionals section for a
better understanding of how the optional fields work.

## Selecting records from the index using checkboxes (multi_select)
The idea behind working with collections is that you end up as a `GET` request at:
`+controller+/collection_edit?ids[]=2&ids[]=3` etc. How you achieve this
is totally up to yourself, but this gem provides you with a nice
standard way of selecting records from the index page. To filter records
to a specific subset the [ransack](https://github.com/activerecord-hackery/ransack)
gem also provides a nice way to add filtering to the index page. To add
checkbox selecting to your page this gem assumes the following
structure using the [Slim lang](http://slim-lang.com/)
[app/views/employees/index.html.slim](spec/dummy/app/views/employees/index.html.slim)
```slim
h1 Listing Employees
table.with-selection
  thead
    tr
      th Name
      th Section
  tbody
    - @employees.each do |employee|
      tr data-record=employee.attributes.to_json
```
Note that each row needs a json version of the record at least
containing its id.<br>
Implement the multiselect dependencies in your manifest files, typically
being `app/assets/javascripts/application.js`:
```javascript
//= require record_collection/multi_select
```
And for the styling provided by this gem ([app/assets/stylesheets/application.css](spec/dummy/app/assets/stylesheets/application.css.sass)):
```css
/*
 *= require record_collection/multi_select
 */
```
{'fraction_non_alphanumeric': 0.09037155413503796, 'fraction_numerical': 0.0010387534958050339, 'mean_word_length': 4.717679305619004, 'pattern_counts': {'":': 0, '<': 15, '<?xml version=': 0, '>': 13, 'https://': 10, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5228254', 'n_tokens_mistral': 3569, 'n_tokens_neox': 3408, 'n_words': 1378}