Search code examples
ruby-on-railshas-manymodel-associationsbelongs-to

Ruby on Rails: finding a model instance from a different controller


Currently I have a has_many and belongs_to association between a Project model and a Invitation model. I have a form_form invitation in the show action of the projects controller.

projects/show.html.erb

<div class="center">
    <h1><%= @project.title %></h1>

    <%= form_for @invitation do |f| %>
        <%= f.collection_select :user_id, User.all, :id, :first_name %><br>
        <%= f.submit "Send Invitation", class: "btn btn-primary" %>
    <% end %>
</div>

Choosing a target user and submitting the form will take the current user to the 'new' invitation page, and the user_id will have been saved for the new invitation. However, I also need a project_id to be saved, and I cannot figure out how I could do this. I was trying to see if I can define an instance variable @project in the 'create' action of the invitations_controller but I can't find out how.

invitations_controller.rb

class InvitationsController < ApplicationController
def new
    @invitation = Invitation.new
end

def create
    @invitation = @project.create_invitation(invitation_params)
    if @invitation.save
        flash[:success] = "Invitation sent!"
        redirect_to @invitation
    else
        render 'new'
    end
end

def show
    @invitation = Invitation.find(params[:id])
end

private
    def invitation_params
        params.require(:invitation).permit(:user_id, :project_id, :description)
    end
end

Please help me out. Thanks!


Solution

  • Simplest way is add the id as a hidden field. Your strong params should take care of project_id it looks like:

    <%= form_for @invitation do |f| %>
        <%= f.hidden_field :project_id, @project.id %>
        <%= f.collection_select :user_id, User.all, :id, :first_name %><br>
        <%= f.submit "Send Invitation", class: "btn btn-primary" %>
    <% end %>
    

    Then in your controller, just use the params to make a new one. Passing the id through the new method will associate the record for you.

    def create
      @invitation = Invitation.new invitation_params
      if @invitation.save
        flash[:success] = "Invitation sent!"
        redirect_to @invitation
      else
        render 'new'
      end
    end
    

    Also note, when you call create_invitation that actually calls the create method right there. So it's already saved. The corresponding to new where it's just built in memory is build_invitation(invitation_params)