AnthonyGalli.com AnthonyGalli.com - 7 months ago 24
Ruby Question

How to prepopulate _form for featured objects?

A user can input a custom

:action
or choose a featured
:action
:

<%= f.text_field :action %>
Or choose a featured challenge:
<%= f.collection_radio_buttons :action, [['Run a Mile','Run a Mile'], ['Drink 16oz of Water','Drink 16oz of Water'], ['Take a Picture','Take a Picture'], ['1 Drink Max','1 Drink Max'], ['See Eiffel Tower','See Eiffel Tower'], ['Write a Book','Write a Book'], ['Skydive','Skydive'], ['Start a Business','Start a Business'], ['No Snooze','No Snooze'], ['Visit All 50 States','Visit All 50 States'], ['Talk to a Stranger','Talk to a Stranger'], ['Try a New Recipe','Try a New Recipe'], ['Media-fast','Media-fast']], :first, :last %>


If a user chooses a featured
:action
the new challenges/_form is pre-populated with his chosen
:action
, but now I'd like to take it to the next level with your help!

<%= form_for(@challenge) do |f| %>
Challenge: <%= f.text_field :action %>
Do On: <%= f.collection_check_boxes :committed %>
Do For: <%= f.number_field :days_challenged %>
<% end %>


How can I pre-populate the other attributes of a featured challenge like, "Do For" or "Do On"?

For example if a user chose the featured
:action
:
'Run a Mile
then I would pre-populate the form with
Run a Mile
,
Mon, Wed, Fri
,
30 Days
.

Answer

You can use simple_form with reform. Reform will give you form object, where you can override methods that will populate your form.

Here is a watered-down example (you will have to adjust it to your case):

class ChallengeForm < Reform::Form
  property :action
  property :committed
  property :days_challenged

  model :challenge

  def commited
    super || action_to_commited_hash[model.action]
  end

  def days_challenged
    super || action_to_days_challenged_hash[model.action]
  end

  def action_to_days_challenged_hash
    {
      'Run a Mile' => 30,
      'Take a Picture' => 12
    }
  end

  def action_to_commited_hash
    {
      'Run a Mile' => ['Mon', 'Wed', 'Fri'],
      'Take a Picture' => ['Tu', 'Thu']
    }
  end
end

super in the methods above will delegate to the model. Note that you are overriding getter methods, and it doesn't affect setters (you can override setters too if you wanted to change form data before writing it).

In your template, instead of

form_for @challenge

you will have:

simple_form_for @form

It's a super common form library for Rails and I can't imagine not using it myself!