Dre
Dre

Reputation: 151

Custom field implementation

I am attempting to add "custom fields" to a sales application (Ruby 2, Rails 4, Postgres).

Here is the relevant schema:

relevant database schema

What's the best way to go about implementing this? values is polymorphic and fields is one-to-many with accounts.

Is there a way to loop over the fields and grab the associated value?

Upvotes: 1

Views: 449

Answers (2)

Frederick Cheung
Frederick Cheung

Reputation: 84114

Using the helpers like text_field requires that there be a getter method for the attribute named. Rails will use that to pre populate the field.

The builtin approach to forms that span multiple models is nested attributes.

If you add accepts_nested_attributes_for :values to your sale model then

= @sale.fields_for :values do |value_form|
  = value_form.label :data, value_form.object.field.label
  = value_form.text_field :data 

Should render labels and text fields for each of your values (the block will be yielded to once for each value).

Alternatively you could eschew the rails helpers altogether.

If in instead you put in your form

= text_field_tag "sale[values_hash][#{v.field.label}]", v.data

Then it should render with no changes to the model. When the form submits params[:sale][:values_hash] will be a hash of the field labels to the entered values. You would need a values_hash= method on your model or the save would blow up. If you continue far enough down this route you'll end up with rails' nested attributes, although this may give you more control.

There are other approaches to complex forms in rails. One is to create form objects who are solely responsible for marshalling data between persistence objects and there form representation, isolating the form from having to know that attribute X is stored in a separate table and that sort of thing

Upvotes: 1

coreyward
coreyward

Reputation: 80041

I could be mistaken on what your issue is, but I think Rails is calling your whatever-custom-field-label-is method because it's trying to get an initial/default value for the input.

Upvotes: 3

Related Questions