user2136807
user2136807

Reputation: 281

Form for one model in view for another

I am writing a simple rails app and I currently have 2 models, Location User, that have the same relationship to the Message model. That is, Location has many messages, User has many messages, and Message belongs to User and Location. I am currently trying to add a form to create a new message on my Location show view. Here is some code:

app/views/locations/show.html.erb:

<h1><%= @locaton.name %></h1>
<p><%= @location.location %></p>
<p><%= @location.discription %></p>
<%= link_to "Find a Different Location", crags_path %>

<h2> Messages
<ul>
    <% @location.messages.each do |message|%>
    </li>
        <h3><%=message.user.username%></h3>
        <p><%=message.content%></p>
    </li>
    <% end %>
</ul>

Locations Controller:

class LocationsController < ApplicationController

def index
    @locations = Location.all
end

def show
    @location = Location.find(params[:id])
end

def new
    @Location = Location.new
end

def create
    @location = Location.new(
        name: params[:location][:name],
        location: params[:location][:location],
        discription: params[:location][:discription])
    @location.save
    flash.notice = "#{@location.name} Created!"
    redirect_to location_path(@crag)
end

def edit
    @location = Location.find(params[:id])
end

def update
    @location = Location.find(params[:id])
    @location.update_attributes(params[:location])

    flash.notice = "#{@location.name} Updated!"

    redirect_to crag_path(@location)
end

def destroy
    @location = Location.find(params[:id])
    @location.destroy
    flash.notice = "#{@location.name} deleted."
    redirect_to locations_path
end

end

MessagesController

class MessagesController < ApplicationController

def new
    @message = Message.new
end

  def create
    @message = current_user.messages.build(
                          content: params[:message][:content])
    redirect_to crags_path                   
  end

end

Form partial that I am trying to include in location/show.html.erb

<%= form_for(@message) do |f| %>
<p>
    <%= f.label "Leave a Message" %>
    <%= f.text_area :content %>
</p>
<%= f.submit "submit" %>
<% end %>

When I try to include the partial i get the following error

undefined method `model_name' for NilClass:Class

and I assume that the form is trying to communicate with the locations controller since it is in a locations view, and since it cant find the instance @message in the locations controller, it doesn't know what to do. I am trying to figure out how to include this form from messages controller in the view for locations. If i create a view for new_message_path it works fine, again, I am guessing because it is functioning within the message views so it referes back to the messages controller.

I also was wondering if there was any way to creat a message that is linked to both current_user and to the location where the form is (or hopefully will be when I figure out the last problem. A message object has a location_id attribute, how do I use the page that I am currently on (with url /locations/location_id) to link the message to that location? Thanks!

Upvotes: 0

Views: 150

Answers (1)

zkcro
zkcro

Reputation: 4344

Firstly, you'll need to actually set the @message variable to a new message in the controller:

# locations_controller.rb
def show
  @location = Location.find(params[:id])
  @message = @location.messages.build(user_id: current_user.id)
end

Using @location.messages.build will automatically populate the location_id with @location.id for the new message, and we're setting the user_id here too.

With that in place, you should be able to build the form in your page (although you might need to add some hidden fields to store the user_id and location_id for @message).

With that done, you can trim down your messages_controller too. Unless you want to have an additional page to create a new message not tied to a location, you can probably get rid of your new action (and route). Then you can simplify your create action to:

# messages_controller.rb
def create
  @message = Message.new(params[:message])
  if @message.save
    # whatever you want to do on successful save, for example:
    flash[:success] = "Message created."
    redirect_to location_path(@message.location_id)
  else
    # whatever you want to do if saving fails
  end
end

Upvotes: 0

Related Questions