简体   繁体   中英

How do I pass in a nested model relationship via a form_for tag in rails

I have a Conversation model which has an initiator , and a recipient attribute, both of which are User models.

When creating a form_for @conversation how do I pass along @conversation.initiator = User.first and @conversation.recipient = User.third ?

class Conversation < ApplicationRecord
  belongs_to :initiator, foreign_key: :initiator_id, class_name: 'User'
  belongs_to :recipient, foreign_key: :recipient_id, class_name: 'User'
end

class User < ApplicationRecord
  has_many :conversations
end

As you have mentioned that any object of conversation will have initiator, and a recipient attributes, then it would go like following:

def new_form
    @conversation = Conversation.new(initiator: User.first, recipient: User.third)
end

Now your both values are available with your model object @conversation, which you can access anywhere in the form, like as follows:

new.html.erb

<%= form_for @conversation do |f| %>
    <%= f.text_field :body, :value => @conversation.initiator %>
<% end %>

Hope this helps you.

Warning:

If you're making an actual messaging app, don't use the code as is.

Never allow users to manipulate sensitive data. In the example below, someone named Alice can edit the hidden field and inject Bob's id, thereby sending a message from Bob's account.

I actually fetched Alice's from devise's current_user helper, and used pundit to ensure authorization.

Solution:

Fixed it, turns out the hidden_field tag first param has to be a @variable written as a symbol ( :variable ), and the second has to be a :attribute

Then you can find it under param[:variable] #> {attribute: value}

IMHO this is a stupid and non-intuitive way of getting this done, but hey, it works. Then you can strong param it and load it up in a model.

Here's the code:

in my controller's new method:

# GET /conversations/new
def new
  @conversation = Conversation.new
  @initiator = User.first
  @recipient = User.second
end

Then in new.html.erb :

<%= form_for @conversation do |f| %>
  <%= f.text_field :subject, class: "form-control" %>

  <%= hidden_field :initiator, :id %>
  <%= hidden_field :recipient, :id %>

  <%= f.button 'Submit', class: 'btn-primary pull-right' %>
<% end %>

Then in the controller's create method:

  def create
    @conversation = Conversation.new(conversation_params)

    @conversation.initiator = User.find_by(initiator_form_params)
    @conversation.recipient = User.find_by(recipient_from_params)

    if @conversation.save
      redirect_to :back, notice: 'Conversation was successfully created.'
    else
      redirect_to :back, notice: 'Conversation was not sent!'
    end
  end

And create strong params

  private

    def conversation_from_params
      params.require(:conversation).permit(:subject)
    end

    def initiator_from_params
      params.require(:initiator).permit(:id)
    end

    def recipient_from_params
      params.require(:recipient).permit(:id)
    end

You're welcome, future me.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM