I have a Threads controller and Messages controller.
Threads has_many Messages
Once a user clicks send, I send data into Threads controller to create the thread. I want to make it to so that
threads_controller.rb
def create
...
if @thread.save
#send data into messages_controller
#to create the corresponding table for a message with this thread_id
end
So, essentially I am trying to do two POSTS one after another if the first one succeeds.
I think redirect_to is what I am supposed to use. Is it possible to use redirect_to to pass params and call create action from a different controller?
EDIT:
I have to have a Thread(bad name choice for the reason Ryan mentioned, but for the sake of not confusing people with answers on the bottom, let's keep it) Model and Message Model here. Thread table needs to only take in the message_title. The Message table takes in from_id(id of user sending message), to_id(id of user receiving message), and message_content. I am trying to do all of this in one form that takes in message_title and message_content.
I hope this helps in understanding the question.
Thanks everyone
I think you're going about this in the wrong way.
First: I really hope that you're not calling a model Thread
, as that would conflict with the Ruby class Thread
. If you are, choose a different word.
Now with the "please aim the gun away from your foot" message out of the way...
You shouldn't be calling out to the MessagesController
to create a new message for the controller. Instead, you should be using nested attributes in the new thread form:
<%= form_for @thread do |f| %>
<%= f.fields_for :messages do |message| %>
<%= render "messages/form", :message => message %>
<% end %>
<% end %>
Inside your DiscussionThread
(I am assuming the name of it here) model, you would then have these lines:
has_many :messages
accepts_nested_attributes_for :messages
You may have to add messages_attributes
to the attr_accessible
attributes in this model too.
This tells the DiscussionThread
model that instances can accept attributes for the messages
association too. In your ThreadsController
the action would then remain the same.
For more information about nested attributes, I recommend watching the Railscasts on Nested Forms #1 and Nested Forms #2.
If I understand your question, all you would need to do is call the create method on the Message model and pass in the relevant information. So so something like this in your if @thread.save:
Message.create(:item_1 => params[:item_1])
If you don't want to go this route, you could use nested resources and then let Rails automagically create the new Message when you pass it the correct information.
There's no reason to go to another controller. You can either, in threads controller go:
@thread.messages << Message.new(...)
or do it in the messages controller, which makes more sense to me, since your users are creating messages with thread creation as a side effect. If you send the thread_id
properly, in params[:message][:thread_id]
the association will be made automatically when you create your object:
@message = Message.create(params[:message])
If you need some other logic to decide which thread a message is associated with, just set the thread_id
directly:
@message.thread_id = current_thread.id # Or Thread.create(...) or whatever
@message.save
I'm seeing your underlying use cases as:
- create new message and thread
- create new message in existing thread
- view message
- view thread and all associated messages
I would suggest a many to many relationship:
http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#method-i-has_and_belongs_to_many
# define has and belongs to many relationship
class Message
has_and_belongs_to_many :threads
end
class Thread
has_and_belongs_to_many :messages
end
class MessageThread
belongs_to :message
belongs_to :thread
end
# use case: creating a new message and a new thread, showing message
class MessagesController < ApplicationController
def create
@message = current_user.messages.create! :text => params[:text]
@thread = @message.threads.create!
end
def show; @message = current_user.messages.find(params[:id); end;
end
# use case: creating a message in an existing thread
def MessagesThreadsController < ApplicationController
def create
@thread = current_user.threads.find params[:id]
@thread.messages.create! :text => params[:text]
end
end
# use case: viewing all messages in a thread
def ThreadsController < ApplicationController
before_filter :set_thread
def show
@thread = current_user.threads.find params[:id]
@messages = @thread.messages
end
end