ruby-on-railsformsroutesnested-resources

Obtaining nested resource id form URL



I have made a nested resources (as below). While being on a coffee_profile#show view, create a specific recipe for that one particular profile via link (/coffee_profiles/:coffee_profile_id/recipes/new(.:format)).

resources :coffee_profiles do 
  resources :recipes, only: [:new, :create, :show]
end

I wanted to catch coffee_profile_id that is present in URL for reference to which coffee_profile does the recipe belong and hide in in recipes#new form in hidden_field just to pass it with other parameters while submitting.

However, I don't know how to get that id itself, hidden_field creates this param, but it is populated with nil after submitting coffee_profile_id: ''


this is from recipes_controller.rb

def new
  @recipe = Recipe.new 
end 

def create
  @recipe = current_user.recipes.build(recipe_params)
  if @recipe.save
    flash[:success] = "Recipe created!"
    redirect_to root_path
  else
    flash[:error] = @recipe.errors.inspect
    render :new
  end
end


And this is recipes#new form_for:

<%= form_for(@recipe) do |f| %>
  ...
<% end %>

Any help is appreciated and let me know if You need more info/code.

console log


Solution

  • Because you are using nested resources, somehow coffee_profile has to be present.

    There is actually no need to store you recipe somewhere, because your recipe has a has_many and belongs_to relationship.

    You need to change your form like so:

    <%= form_for([@coffee_profile, Recipe.new]) do |f| %>
        <div class="recipes_form_item">
          <%= f.label :coffee %>
          <%= f.text_field :coffee %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :quantity %>
          <%= f.number_field :quantity %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :method %>
          <%= f.text_field :method %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :water_temperature %>
          <%= f.number_field :water_temperature %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :water_amount %>
          <%= f.number_field :water_amount %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :grind %>
          <%= f.text_field :grind %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :aroma %>
          <%= f.text_field :aroma %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :aroma_points %>
          <%= f.number_field :aroma_points %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :taste %>
          <%= f.text_field :taste %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :taste_points %>
          <%= f.number_field :taste_points %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :body %>
          <%= f.text_field :body %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :body_points %>
          <%= f.number_field :body_points %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :astringency %>
          <%= f.text_field :astringency %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :astringency_points %>
          <%= f.number_field :astringency_points %>
        </div>
        <div class="recipes_form_item">
          <%= f.label :brew_time %>
          <%= f.number_field :brew_time %>
        </div>
        <div class="recipes_form_item">
          <%= f.submit :Submit %>
        </div>
      <% end %>
    

    now, inside your coffee_profile_controller, add in your new method (or wherever you render the form for your Recipe:

    @coffee_profile = CoffeeProfile.find(params[:id])
    

    Now, inside your recipe_controller add inside create:

    @coffee_profile = CoffeeProfile.find(params[:id])
    @recipe = @coffee_profile.recipes.create(recipe_params)
    
    if @recipe.save
     redirect_to root_path
    end
    

    change also inside the new method everything like so:

    def new @coffee_profile = CoffeeProfile.find(params[:id]) @recipe = @coffee_profile.recipe.new end

    and for the recipe_params, make sure that you are accepting :coffee_profile_id

    params.require(:recipe).permit(:id, your other values and :coffee_profile_id)
    

    Now, when you go to your console you can say: @recipe = Recipe.last

    and then @recipe.coffee_profile, which will give you all information back about the coffee profile.

    Greetings!