Hommer Smith
Hommer Smith

Reputation: 27852

Form has_many in text_area

I have the following situation:

A Order has many Pages. I want to let the User to paste a bunch (20+) URLs (it's a Page attribute) that they might have in a doc file into a text area.

Right now I am not using a Form associated with an Order object, because I fail to see how I can do a nested form of the URLs if those are inside a text area.

I have seen a similar question has been asked before here: Rails: Using a Textarea for :has_many relationship , but I fail to see how would I code the view and model in order to do so.

So, if I have this:

Order has_many Pages

And a form like this:

<%= form_for @order do |f| %>
  <%= f.text_area :page_urls?? %> # This would let the user paste X URLs, which would be 
                                   # used to create X Pages associated with the Order.
<% end %>

Upvotes: 1

Views: 150

Answers (2)

Gjaldon
Gjaldon

Reputation: 5644

You could retain the view code that you have:

<%= form_for @order do |f| %>
  <%= f.text_area :page_urls %>
  #other field and submit button
<% end %>

In your model, you'll need to do the following:

attr_accessor :page_urls

after_validation do
  if page_urls
    parse_page_urls.each do |url|
      pages.create(url: url)
    end
  end
end

def parse_page_urls
  #use regexp to extract urls from page_urls string and return an array of url strings
end

The accessor is defined so that you can use :page_urls in your form_builder. You could set easily validations in your model for :page_urls that way too.

Once order has been validated, it will create page objects according to the number of urls extracted from the page_urls attribute.

You could refer to this for some help with using regexp to extract the urls from the string.

Hope that helps!

Upvotes: 1

IT Ninja
IT Ninja

Reputation: 6438

This is a job best handled with nested form. It will let you submit attributes of a has_many relationship model from the parent model, like you wish to do. For example, from its docs:

Imagine you have a Project model that has_many :tasks. To be able to use this gem, you'll need to add accepts_nested_attributes_for :tasks to your Project model. If you wish to allow the nested objects to be destroyed, then add the :allow_destroy => true option to that declaration. See the accepts_nested_attributes_for documentation for details on all available options.

This will create a tasks_attributes= method, so you may need to add it to the attr_accessible array (attr_accessible :tasks_attributes).

Then use the nested_form_for helper method to enable the nesting.

<%= nested_form_for @project do |f| %>

You will then be able to use link_to_add and link_to_remove helper methods on the form builder in combination with fields_for to dynamically add/remove nested records.

<%= f.fields_for :tasks do |task_form| %>
  <%= task_form.text_field :name %>
  <%= task_form.link_to_remove "Remove this task" %>
<% end %>
<%= f.link_to_add "Add a task", :tasks %>

In response to your comment:

In order to do something like that, you would need to do processing in the controller to separate the URL's, then make a new Page object associated with @order object. Unfortunately, there isn't a way to do this without post-processing, unless you do it with JS on the client side with hidden inputs.

Upvotes: 0

Related Questions