<commit_before># hstore_radio_buttons

So, you need a bunch of radio buttons on a form. But there's no particular reason for you to save each question in its own database field. And, even better, you have access to the Hstore data type in postgres. hstore_radio_buttons is the library you are looking for. Define a set of radio buttons, display them in your form and then gather them all up and save the data in an hstore field.

# Requirements

- Postgres. If you have the hstore extension enabled, great. If not, the
  migration generated by this gem will turn it on.
- Rails 3 and the activerecord-postgres-hstore gem installed

This might work with Rails 4, which has native support for hstore, but I haven't tried that yet.

## Installation

Add this line to your application's Gemfile:

    gem 'hstore_radio_buttons'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install hstore_radio_buttons

hstore_radio_buttons will save all of your hstores in a single table. To
generate that table, do:

    $ rails generate hstore_radio_buttons:migration
    $ rake db:migrate

The migration does two things:

1. Executes the command "CREATE EXTENSION IF NOT EXISTS hstore"
2. Creates a polymorphic table hstore_radio_data, which is where all the
   persisted data will be saved.

If you don't need to set up the hstore extension, just remove that part
of the migration before running it.

## Usage

For every collection of radio button questions, you'll need to define their set of values as well as a label for the set of buttons. Say you want something like this:

    Gender:
      o Male
      o Female
      o Other
  
    Favorite Barn Animal:
      o Cow
      o Sheep
      o Pig

### Defining buttons in a YAML file

In above example we have two sets of buttons, one for the Gender question and one for the Barn Animal question. Each set needs to be defined in a yaml file that lives in config/hstore_radio_button_sets.yml

    ---
    person:
      gender:
      - male
      - female
      - other
      'favorite barn animal':
      - cow
      - sheep
      - pig

The above defines two sets of buttons that can be used by the person model. For a model to generate/save radio button data, the set must be defined for the model.

Then set up your model so that it knows it has hstore_radio_buttons.

    class Person < ActiveRecord::Base
      include HstoreRadioButtons

      hstore_radio_buttons_from_yaml
      ...
    end

### Defining buttons with macros in the model itself

Instead of using the yaml file, you can define your buttons macro-style
within the model itself.

    class Report < ActiveRecord::Base
      include HstoreRadioButtons

      hstore_radio_button Hash['viewed' => ['true', 'false']]
      hstore_radio_button Hash['written by' => %w(monkeys interns milton)]
    end

### Getters, Setters, Security

Adding the button sets gives you getters and setters for those sets:

    >> p = Person.find(1)
    >> p.gender 
      => 'female'
    >> p.favorite_barn_animal
      => 'sheep'
    >> p.favorite_barn_animal = 'pig'
      => 'pig'

Keep in mind that the returned data will always be strings. So boolean
values aren't true and false, they are 'true' and 'false'. That's just
how hstore works.

And, for the sake of security, you can't set a value to
something that's not in your button definition. So if someone changes their
form submission values to include malicious data that should not be a
problem.<sup>*</sup>


    >> p = Person.find(1)
    >> p.gender = 'something hackerish' 
      => nil

<sup>*</sup> Notice the 'should' part there. I am not a security expert
and I welcome any pull requests that make this gem more secure.

Validations from ActiveModel work as well. So you can do:

    class Person < ActiveRecord::Base
      ...
      validates_presence_of :gender
    end

Or whatever other validations you need.

### Displaying buttons in a form

To display the radio button set on the form, you have two options:

    <%= form_for @person do |f|>
      <%= f.hstore_radio_tag('gender') %>
      <%= f.hstore_radio_tag('favorite barn animal') %>
    <% end>

Or, you could render all radio sets defined for your model:

    <%= form_for @person do |f|>
      <%= f.hstore_radio_tags %>
    <% end>

Which would render both Gender and Favorite Barn Animal in the same order in which they appear in the yaml file.

The exact html that gets rendered in the above example would be:

    <form...>
      <label for=''>Gender</label>
      <input type='radio' name='' value='male'>Male</input>
      <input type='radio' name='' value='female'>Female</input>
      <input type='radio' name='' value='other'>Other</input>
      ...
    </form>

### Persistence

The conversion of your data into an hstore is handled by
[activerecord-postgres-store]
(https://github.com/engageis/activerecord-postgres-hstore) so refer to
their documentation.

Your data will be stored in the hstore_radio_data table. If you saved
data for a Person with the id of 1, it will be saved as

    model_id  model_type  hstore_data
    1         Person      {'gender' => 'other'....}

But it's easiest to just work with the getters and setters in the Person
model than dealing directly with this table.

And, of course, this perisisted data is used to mark the correct radio
buttons as 'selected' when the form is loaded later.

TODO: It'd be nice to have default values for a set.  

## Contributing
<commit_msg>Preparing for working on the view code by updating the readme to reflect what I think the api will be.<commit_after># hstore_radio_buttons

So, you need a bunch of radio buttons on a form. But there's no particular reason for you to save each question in its own database field. And, even better, you have access to the Hstore data type in postgres. hstore_radio_buttons is the library you are looking for. Define a set of radio buttons, display them in your form and then gather them all up and save the data in an hstore field.

# Requirements

- Postgres. If you have the hstore extension enabled, great. If not, the
  migration generated by this gem will turn it on.
- Rails 3 and the activerecord-postgres-hstore gem installed

This might work with Rails 4, which has native support for hstore, but I haven't tried that yet.

## Installation

Add this line to your application's Gemfile:

    gem 'hstore_radio_buttons'

And then execute:

    $ bundle

Or install it yourself as:

    $ gem install hstore_radio_buttons

hstore_radio_buttons will save all of your hstores in a single table. To
generate that table, do:

    $ rails generate hstore_radio_buttons:migration
    $ rake db:migrate

The migration does two things:

1. Executes the command "CREATE EXTENSION IF NOT EXISTS hstore"
2. Creates a polymorphic table hstore_radio_data, which is where all the
   persisted data will be saved.

If you don't need to set up the hstore extension, just remove that part
of the migration before running it.

## Usage

For every collection of radio button questions, you'll need to define their set of values as well as a label for the set of buttons. Say you want something like this:

    Gender:
      o Male
      o Female
      o Other
  
    Favorite Barn Animal:
      o Cow
      o Sheep
      o Pig

### Defining buttons in a YAML file

In above example we have two sets of buttons, one for the Gender question and one for the Barn Animal question. Each set needs to be defined in a yaml file that lives in config/hstore_radio_button_sets.yml

    ---
    person:
      gender:
      - male
      - female
      - other
      'favorite barn animal':
      - cow
      - sheep
      - pig

The above defines two sets of buttons that can be used by the person model. For a model to generate/save radio button data, the set must be defined for the model.

Then set up your model so that it knows it has hstore_radio_buttons.

    class Person < ActiveRecord::Base
      include HstoreRadioButtons

      hstore_radio_buttons_from_yaml
      ...
    end

### Defining buttons with macros in the model itself

Instead of using the yaml file, you can define your buttons macro-style
within the model itself.

    class Report < ActiveRecord::Base
      include HstoreRadioButtons

      hstore_radio_button Hash['viewed' => ['true', 'false']]
      hstore_radio_button Hash['written by' => %w(monkeys interns milton)]
    end

### Getters, Setters, Security

Adding the button sets gives you getters and setters for those sets:

    >> p = Person.find(1)
    >> p.gender 
      => 'female'
    >> p.favorite_barn_animal
      => 'sheep'
    >> p.favorite_barn_animal = 'pig'
      => 'pig'

Keep in mind that the returned data will always be strings. So boolean
values aren't true and false, they are 'true' and 'false'. That's just
how hstore works.

And, for the sake of security, you can't set a value to
something that's not in your button definition. So if someone changes their
form submission values to include malicious data that should not be a
problem.<sup>*</sup>


    >> p = Person.find(1)
    >> p.gender = 'something hackerish' 
    >> p.gender = nil

<sup>*</sup> Notice the 'should' part there. I am not a security expert
and I welcome any pull requests that make this gem more secure.

Validations from ActiveModel work as well. So you can do:

    class Person < ActiveRecord::Base
      ...
      validates_presence_of :gender
    end

Or whatever other validations you need.

### Displaying buttons in a form

To display the radio button set on the form, you have three options:

#### Use a helper to display a single radio button

    <%= form_for @person do |f|>
      <%= f.hstore_radio_tag('gender') %>
      ...
      <%= f.hstore_radio_tag('favorite barn animal') %>
    <% end %>

#### Use a helper to display all the radio buttons

    <%= form_for @person do |f|>
      <%= f.hstore_radio_tags %>
    <% end %>

#### Use the Rails radio button helpers:

    <%= form_for @person do |f|>
      <%= f.radio_button('gender', 'male') %>
      <%= f.label('gender', "Male", :value => 'male') %>
      ...etc...
    <% end %>

The above duplicates the values of your radio buttons, though. Now they
are in the yaml file (or model), and in your view. No one likes
duplications. You can also do:

    <%= form_for @person do |f|>
      <% @person.gender_options.each do |option| %>
        <%= f.radio_button('gender', option) %>
        <%= f.label('gender', option.titleize, :value => option) %>
      <% end %>
    <% end %>

When using the `hstore_radio_tag` or `hstore_radio_tags` helpers, the
html rendered will be:

    <input type='radio' name='person_gender' value='male'>
    <label for='person_gender' value='male'><br />

### Persistence

The conversion of your data into an hstore is handled by
[activerecord-postgres-store]
(https://github.com/engageis/activerecord-postgres-hstore) so refer to
their documentation.

Your data will be stored in the hstore_radio_data table. If you saved
data for a Person with the id of 1, it will be saved as

    model_id  model_type  hstore_data
    1         Person      {'gender' => 'other'....}

But it's easiest to just work with the getters and setters in the Person
model than dealing directly with this table.

And, of course, this perisisted data is used to mark the correct radio
buttons as 'selected' when the form is loaded later.

TODO: It'd be nice to have default values for a set.  

## Contributing

{'fraction_non_alphanumeric': 0.07402880838061981, 'fraction_numerical': 0.001396769969445657, 'mean_word_length': 3.18560467665327, 'pattern_counts': {'":': 0, '<': 54, '<?xml version=': 0, '>': 89, 'https://': 2, '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': '843496', 'n_tokens_mistral': 3397, 'n_tokens_neox': 3204, 'n_words': 1555}