Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested form, two levels deep #454

Open
domi91c opened this issue Apr 30, 2018 · 11 comments
Open

Nested form, two levels deep #454

domi91c opened this issue Apr 30, 2018 · 11 comments

Comments

@domi91c
Copy link

domi91c commented Apr 30, 2018

I had my Reform form working with one nested model, but I need that model to contain another nested model. A tutorial has_many steps, a step has_many images. Here's my attempt:

class TutorialForm < Reform::Form

  collection :steps, populator: :step_populator! do
    property :title
    property :body
    validates :title, presence: true
    validates :body, presence: true
    collection :images, populator: :image_populator! do
      property :image
      validates :image, presence: true
    end
  end

  def step_populator!(collection:, index:, **)
    if (item = collection[index])
      item
    else
      collection.insert(index, Step.new)
    end
  end

  def image_populator!(collection:, index:, **)
    if (item = collection[index])
      item
    else
      collection.insert(index, Image.new)
    end
  end
end

Is this totally wrong? It's not working at the moment.

@apotonick
Copy link
Member

Keep in mind that populators are only called when the incoming document contains a corresponding fragment.

"Not working" - what is "not working"? 😂 Does your computer start up? Have you plugged in the power cable? Does the form validate? What's missing? What's your input hash? What's the resulting form?

@unrooty
Copy link

unrooty commented Jul 9, 2018

@domi91c did you solve this problem?

@unrooty
Copy link

unrooty commented Jul 9, 2018

@apotonick the problem is that I can't use collection in collection on form. For example I have such code in Reform::Form:

collection :contacts, populate_if_empty: Contact do
      properties :first_name, :last_name, :agency_id, :nickname,
                 :middle_name, :suffix, :prefix, :title

      collection :phones, populate_if_empty: ContactPhone, populator: ->(fragment:, **) {
        return skip! if fragment['delete'] == 'true' && !fragment['id']

        if fragment['id']
          item = phones.find_by(id: fragment['id'])
          phones.delete(item) if fragment['delete'] == 'true' && !item.primary
          item ? item : phones.append(model.phones.build)
        else
          phones.append(model.phones.build)
        end
      } do
        properties :number, :type, :primary
        validates :number, presence: true
      end
    end

and on view I have (just for tests):

<%= f.fields_for :contacts, form.model.contacts.presence || form.model.contacts.build do |ff| %>
      <%= ff.text_field :first_name %>
      <%= ff.hidden_field :agency_id, value: 1 %>
      <%= ff.text_field :last_name %>
      <%= ff.fields_for :phones, form.model.contacts.last.phones || form.model.contacts.last.phones.build do |fff| %>
        <%= fff.text_field :number %>
        <% end %>
    <% end %>

but rails throws error:

undefined method 'number' for #<ContactPhone::ActiveRecord_Associations_CollectionProxy:0x00007f011fb512e8>

When I write accept_nested_attributes :phones in Contact model it works (ContactPhone belongs_to Contact).
Can you tell me how use collection in collection on view, please?

@apotonick
Copy link
Member

Hi @unrooty, please try this puts form.contacts[0].phones on the console. Reform doesn't do anything other than providing you a decorated, well-defined object graph. I am guessing the second argument with the || is the problem, you're creating objects there, I've never seen this before.

@unrooty
Copy link

unrooty commented Jul 10, 2018

@apotonick when I wrote p form.contacts[0].phones, I got

[#<#<Class:0x00007f00f265f000>:0x00007f0117da22c0 @fields={"number"=>"648-822-8073", "type"=>"Work", "primary"=>true}, @model=#<ContactPhone id: 12, number: "648-822-8073", type: "Work", contact_id: 12, created_at: "2018-07-07 12:10:37", updated_at: "2018-07-07 12:10:37", primary: true>, @mapper=#<#<Class:0x00007f0127d8a688>:0x00007f0117da2180 @model=#<ContactPhone id: 12, number: "648-822-8073", type: "Work", contact_id: 12, created_at: "2018-07-07 12:10:37", updated_at: "2018-07-07 12:10:37", primary: true>>, @_changes={}, @errors=#<Reform::Form::ActiveModel::Errors:0x00007f0117da1de8 @base=#<#<Class:0x00007f00f265f000>:0x00007f0117da22c0 ...>, @messages={}, @details={}>>]

But when I tried to pass it to ff.fields_for, I've got error:

undefined method `number' for #<Disposable::Twin::Collection:0x00007f0117da1ca8>

Another thing that I want to say is that after || I build model if it doesn't exists (because fields_for requires it to build right form)

@apotonick
Copy link
Member

The behavior of Reform is correct, it returns an "enumeratable" object for phones, I have no idea how fields_for works, it probably does some bullshit to figure out if it's an array and doesn't see it because of Rails magic and respond_to?? Wouldn't be surprised, has happened before. You need to look into fields_for, Reform is doing the correct thing.

@unrooty
Copy link

unrooty commented Jul 10, 2018

The most strange thing for me that I use two same objects in fields_for, but on top level it work and in nested fields_for it stops working. I start to hate Rails...

@apotonick
Copy link
Member

Well, we wrote the Formular gem to avoid Rails form helpers, but it's still lacking docs.

@unrooty
Copy link

unrooty commented Jul 10, 2018

@apotonick thanks for answers :)

@apotonick
Copy link
Member

Please let me know what is the problem!

@unrooty
Copy link

unrooty commented Jul 10, 2018

@apotonick I didn't find solution and desided to use text_field_tag "account[contacts_attributes][#{ff.index}][phones_attributes][0][number]. It's not good solution but I can't come up anything else...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants