1

I have these models in my Rails app (lots of stuff omitted obviously):

class Invitation < ActiveRecord::Base
  belongs_to :team
  validates :team_id, :presence => true
end

class Team < ActiveRecord::Base
  has_many :invitations
  accepts_nested_attributes_for :invitations

  before_validation :set_invitation_association
  private
    def set_invitation_association
      invitations.each do |invite|
        if invite.new_record?
          # this bit doesn't work since self.id is nil
          invite.team = self
        end
      end
    end
end

Now what I'm trying to do is make it so that the current_user can invite people into his team at the same time as he creates it by using a nested form.

The problem of course is that when I POST team and invitations attributes to the teams_controller, the invitations fail validation because they don't have a team_id. But I can't give them a team_id because the team they are associated with doesn't have one since it hasn't been saved to the database yet.

Is there a way that I can achieve this or do I just have to remove the validation from the invitations model? I'd rather not do this because there are other methods in my app which can send invitations and I wouldn't like to leave myself open to the possibility that I could save an invitation without a team.

Or have I just got the wrong idea and presence validations are just there to make sure that users fill in all the fields rather than to stop the programmer making mistakes!?

Sorry for the waffly question.

<%= form_for(@team) do |f| %>
  <% if @team.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(@team.errors.count, "error") %> prohibited this team from being saved:</h2>

      <ul>
      <% @team.errors.full_messages.each do |msg| %>
        <li><%= msg %></li>
      <% end %>
      </ul>
    </div>
  <% end %>

  <div class="field">
    <%= f.label :name %><br />
    <%= f.text_field :name %>
  </div>

  <h3>Invite some teammates</h3>
  <%= f.fields_for :invitations, @invitation do |invite_fields| %>
    <p>
      <%= invite_fields.label :recipient_name %>
      <%= invite_fields.text_field :recipient_name %><br />

      <%= invite_fields.label :recipient_email %>
      <%= invite_fields.text_field :recipient_email %><br />
    </p>
  <% end %>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>
David Tuite
  • 22,258
  • 25
  • 106
  • 176
  • You have rather the wrong idea about nested attributes. If your form is set up correctly then activerecord will save the team object first, then the invitations, including the team id; you do not need to manually set the association. Posting your form would help your question. – mark Jul 14 '11 at 11:54
  • I see! Well at least I knew I had the wrong idea about something! I edited the question with the form. – David Tuite Jul 14 '11 at 11:57
  • From what I remember that looks ok. Have you tried it without the before_validation method? There are a couple of good screencasts on this. http://railscasts.com/episodes/196-nested-model-form-part-1 http://railscasts.com/episodes/197-nested-model-form-part-2 – mark Jul 14 '11 at 12:01
  • Yeah I just keep getting the validation error: Invitations team can't be blank. I'll watch those screencasts now. Thanks. – David Tuite Jul 14 '11 at 12:06
  • Watched the screencasts, he doesn't have any validations. He doesn't make a point of not having them though. They're just not part of the video. – David Tuite Jul 14 '11 at 12:38
  • possible duplicate of [accepts_nested_attributes_for child association validation failing](http://stackoverflow.com/questions/935650/accepts-nested-attributes-for-child-association-validation-failing) – David Tuite Jul 14 '11 at 13:26

1 Answers1

1

There's a similar question to this here:

accepts_nested_attributes_for child association validation failing

You should discard the validation of team_id in my opnion. It's instantiated as part of the relation by ActiveRecord; as a result of the nested form. If you're creating invitations after a team has been created - this seems likely - then have a conditional validation where the associated team is not a new record.

http://railscasts.com/episodes/41-conditional-validations

Community
  • 1
  • 1
mark
  • 10,316
  • 6
  • 37
  • 58