How to work with a model with slightly different forms in Rails?

Go To StackoverFlow.com

0

Consider a model that has 2 types: A and B. Both types store a color as a string. Type A can be blue or red. Type B can be white or black.

When displaying the form for type A, there is an HTML select list that contains [blue, red]. For type B, the select list contains [white, black].

What is the best method to display these two different selects for the same model?

Switching on type does not work because when you create a new model, there is no type.

Do you need to have two create buttons, one for each type? Or should this be designed as two separate models, inheriting from a common base model?

I considered an AJAX (jQuery) update of the select based on the selection of type. This seems like a very complicated solution to a simple problem.

2012-04-03 23:04
by B Seven
Do you need two models (does the functionality of each type differ)? If it's just a validation issue (i.e. colour restricted by type) then you could put this logic in the model to force a validation error for conflict. From the user's perspective it would be more convenient have the change() handler - RobinGower 2012-04-04 00:03
No, the functionality is very similar, so I think one model is better - B Seven 2012-04-04 00:12


1

Enforcing the color-type restrictions should definitely be done in validations in the model. In order to keep the views consistent with your models, I suggest a bit of javascript:

<select class="type-select">
  <option value="TypeA">Type A</option>
  <option value="TypeB">Type B</option>
</select>

<select class="type-A-opts">
  <option value="blue">Blue</option>
  <option value="red">Red</option>
</select>
<select class="type-B-opts" style="display:none" >
  <option value="black">Black</option>
  <option value="white">White</option>
</select>

<script>
  $(".type-select").change(function(){
    var cur_value = $(this).attr("value");
    if(cur_value == "TypeA"){
      $(".type-A-opts").show();
      $(".type-B-opts").hide();
    }else{
      $(".type-A-opts").hide();
      $(".type-B-opts").show();
    }
  });
</script>
2012-04-04 01:36
by tsherif


1

I suggest optgroup.

<select>
  <optgroup label="type A">
    <option value="blue">Blue</option>
    <option value="red">Red</option>
  </optgroup>
  <optgroup label="type B">
    <option value="black">Black</option>
    <option value="white">White</option>
  </optgroup>
</select> 
2012-04-03 23:43
by Yanhao
That's good but how to enforce the right color for the type - B Seven 2012-04-03 23:53
Each color belongs to either type A or type B. You definitely know the type of a given color - Yanhao 2012-04-04 00:15