Ruby on Rails two create actions to two different

2019-07-20 05:45发布

问题:

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

回答1:

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.



回答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.



回答3:

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


回答4:

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