1

I have a database structure where my Articles have many People (through a join, but that is working fine)

What I would like to happen is that when people create an article they can at the same time create new people

Ie the path should be of the form article/new/people/new

In fact, without using nested routes I managed this by using this approach

article.rb (model)

attr_accessor :new_person

articles_controller.rb

  def create
    @article = Article.new(params[:article])

    if params[:add_person]
      @person = Person.check_if_exists_or_create(@article.new_person["first_name"], @article.new_person["last_name"])
      if @person.save
        @article.people << @person
        @article.new_person = nil
      end
      render :action => "new" and return
    end
...

  end

form.erb

<%= form_for @article  do |f| %>
...

      <%= fields_for :new_person do |p| %>

        <% if @person && @person.errors.any? %>
          <%= render :partial => "shared/error_messages", :object => @person %>
        <% end %>

        <div class="field">
          <%= p.label :first_name, "First Name" %>
          <%= p.text_field :first_name %>
        </div>

        <div class="field">
          <%= p.label :last_name, "Last Name" %>
          <%= p.text_field :last_name %>
        </div>

        <%= submit_tag "Add Person", :name => "add_person" %>

      <% end %>
...
  <p>
    <%= f.submit %>
  </p>


<% end %>

This works OK to an extent but now the form is becoming more complicated with other fields I thought I could refactor it to take advantage of nested routes.

Additionally, it is adding a lot of logic to the create controller - and further down to line I might consider making these actions javascript in which case I understand determining the specific button pressed by a controller is more complicated.

For these reasons I thought that a nested route approach might be a more natural fit.

For existing articles it works fine eg /articles/1/people/new with no problems.

I know that nesting forms is a no-no for html validation reasons among other things so I have tried numerous combinations of form_for and fields_for to achieve the goal of:

on the articles/new page

submitting the main form to articles/new submitting the "sub" form with the new_person fields to articles/new/people/new

and making the change to doing this by UJS as painless as possible

The warmest I think I have got was with this error

No route matches {:controller=>"people", :article_id=>#<Article id: nil, title: nil, published_on: nil, created_at: nil, updated_at: nil, people_count: nil, organizations_count: nil>}

I am guessing that the issue is there is no article_id to relate the person to at that point.

But in fact I am only really interested in adding that person to the database and then creating a relationshop to the article which is then stored when the entire article is saved.

Apologies for the long post but wanted to be comprehensive in my question.

Any advice, including alternative approaches that would fit my objectives better would be much appreciated. I have watched the railcasts relating to nested forms and nested routes and read all I can find online but haven't found a solution to the /model/new/submodel/new form issue.

Many thanks.

Chris
  • 1,054
  • 2
  • 12
  • 24
  • why do you need to create them both at the same time? to avoid articles not having any people? – corroded Mar 29 '11 at 16:30
  • hi corroded, ideally i'd like it to be a one page form. it would be quicker to make entries to it. though a two step process might be an option – Chris Mar 29 '11 at 16:38
  • one page forms with 2 models are common. an alternative way(with a one step process is to create you article already) so you have an existing(unsaved) article that when you save, will include the people in it. caveat on this are there will be articles that might be abandoned(people close the browser halfway through) but this can be done with a cleaner of sorts in a cron job – corroded Mar 29 '11 at 16:40
  • I think I understand you, but is there not a new instance created by Article.new which I have already created and passed into the view from the controller at this point? Or do you mean that I should save the article immediately, then edit it, then delete it? Sorry if I have missed something. Thanks for your time, Chris – Chris Mar 29 '11 at 16:47
  • yup i was meaning that...create an article already so it will be article/1/people/new so even if you see a blank form, you will actually be editing it and adding people to it – corroded Mar 29 '11 at 16:56
  • Hi yeah, I see what you mean, my only problem with doing it that way is that in effect i'll be editing my article page in the show view which I was trying to avoid if possible. Much appreciate the advice though, I might look into doing it that way if I can't find an alternative. – Chris Mar 29 '11 at 18:48
  • well in any case you will be either editing it or refactoring again(either your routes/models) so i guess thats a better alternative – corroded Mar 29 '11 at 18:55
  • It is not possible to do `article/new/people/new`, cause here you are trying to create a person for an article that does not exist. As you had caught it well, shown in statement : > I am guessing that the issue is there is no article_id to relate the person to at that point. You should first create an article then save person. So that, it would come like this `article/2/people/new` – Surya Apr 06 '11 at 06:17

0 Answers0