0

I've a multiple relation table named Order which belongs_to a Relai(to avoid singular/plurials complications), a Customer and a Composition. I set my Order model accordingly with nested_attributes as mentioned below. Before adding the customer part, I want to send a mail with just the @composition and a @relai chose with a dropdown.

class Order < ApplicationRecord
  belongs_to :relai
  belongs_to :composition
  accepts_nested_attributes_for :relai
  accepts_nested_attributes_for :composition
end

I set my OrdersController to get the :composition_id from my params

def new
    @order = Order.new
    @composition = Composition.find(params[:composition_id])
    @relais = Relai.all
  end

  def create
    @florist = Florist.first
    @composition = Composition.find(params[:composition_id])
    #@relai = Relai.find(params[:relai_id])  # If I add this line it returns "Couldn't find Relai without an ID"
    @order = Order.new(order_params)
    if @order.save!
      raise
      OrderMailer.order_mail(@order).deliver
      redirect_to thanks_purchase_path
    else
      render :new
    end
  end

  private

  def order_params
    params.require(:order).permit(
      florist_attributes: [:id],
      relai_attributes: [:id, :name, :address],
      composition_attributes: [:id, :name]
      )
  end

My View:

  <%= form_with(model: @order, url: composition_orders_path(@composition), local: true) do |compo| %>
    <%= compo.collection_select :relai, @relais, :id, :name %>
    <%= compo.fields_for :composition do |fc| %>
      <%= fc.collection_select :composition, @compositions, :id, :name %>
    <% end %>
    # Start Block that doesn't display the Relai.all
    #<%#= compo.fields_for :relai do |fr| %>
     #<%#= fr.label :relai, 'Ici la liste des relais :' %>
     #<%#= fr.association :relai, collection: @relais %>
     #<%#= fr.association :relai, @relais, :id, :name %>
    #<%# end %>
    # End Block
    <%= compo.submit "MAIL", class: "app-form-button" %>
  <% end %>

And the routes:

resources :compositions, only: [:show, :index] do
    resources :orders, only: [:show, :new, :create, :index]
  end

I also tried:

Can someone explain me why I got a "Validation failed: Relai must exist, Composition must exist" whereas these appears in my params?

{"authenticity_token"=>"[FILTERED]", "order"=>{"relai"=>"2"}, "commit"=>"MAIL", "composition_id"=>"3"}

I'm on Rails 6.1.4 ; Ruby 2.6.6

1 Answer 1

0

accepts_nested_attributes_for works from parent to children. You are using it on the child side (Order).

If you just need to assign an existing Relai and Composition to Order just use a select for both of them:

class Order < ApplicationRecord
  belongs_to :relai
  belongs_to :composition
end
  def new
    @order = Order.new
    @compositions = Composition.all
    @relais = Relai.all
  end

  def create
    @order = Order.new(order_params)
    if @order.save!
      OrderMailer.order_mail(@order).deliver
      redirect_to thanks_purchase_path
    else
      render :new
    end
  end

  private

  def order_params
    params.require(:order).permit(:relai_id, :composition_id)
  end  
<%= form_with(model: @order, url: composition_orders_path(@composition), local: true) do |compo| %>
    <%= compo.collection_select :relai_id, @relais, :id, :name %>
    <%= compo.collection_select :composition_id, @compositions, :id, :name %>
    <%= compo.submit "MAIL", class: "app-form-button" %>
<% end %>

EDIT: Setting Composition on the controller.

  def new
    composition = Composition.find(params[:composition_id])
    @order = Order.new(composition: composition)    
    @relais = Relai.all
  end

  def create
    @order = Order.new(order_params)
    if @order.save!
      OrderMailer.order_mail(@order).deliver
      redirect_to thanks_purchase_path
    else
      render :new
    end
  end

  private

  def order_params
    params.require(:order).permit(:relai_id, :composition_id)
  end  
<%= form_with(model: @order, url: composition_orders_path(@composition), local: true) do |compo| %>
    <%= compo.collection_select :relai_id, @relais, :id, :name %>
    <%= compo.hidden_field :composition_id %>
    <%= compo.submit "MAIL", class: "app-form-button" %>
<% end %>
Sign up to request clarification or add additional context in comments.

8 Comments

Thank you for your answer. Indeed I set the accepts_nested_attributes_for on the child. What a dumb move. I put all the accepts_nested_attributes_for on parents (Relai ; Composition ; Customer) aimed on orders. It guess it works because I got another error. It returns me undefined method save!' for nil:NilClass` and my params are set properly! {"authenticity_token"=>"[FILTERED]", "order"=>{"relai_id"=>"2"}, "commit"=>"MAIL", "composition_id"=>"1"}. I removed the <%= compo.collection_select :composition_id, @compositions, :id, :name %> part because @composition is set in the url.
Nvm I forgot the @order = Order.new(order_params) in the create of OrdersController. Now the relai_id is good, but it works only if I put the <%= compo.collection_select :composition_id, @compositions, :id, :name %>. I just need a way to get the :composition_id from the url and not from a collection.select.
<%= compo.collection_select :composition_id, @compositions, :id, :name, {selected: @composition.id}, {class: "no-display"} %> works. Otherwise he throws me an error. Can't use <% tag. Thank you for your help @CAmador
@JoCoz See my edit, please.
Ok it works. I have a last question, all seems to works well except when I submit. I got the mail but with the information from the seed and not from the form. It keeps me the basic information for the price and the size from the seed and I only got the Relay selected from the form. Any idea ?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.