Rails has_many, through form adding variables to joining table












0















I'm trying to build an app for storing recipes so that I can (eventually) build shopping lists based on recipe ingredients.



What I'm struggling with is being able to link ingredients to recipes based on their measures, i.e. a recipe could use 300 grams of flour and one pinch of salt while another recipe might use two cups of flour and one teaspoon of salt.



I've set up the DB with three tables: Recipes, Measures and Ingredients. However I'm getting stuck trying to create the basic form elements so that I can associate the unit (e.g. grams, cups or mL) with the quantity (1 or 500) of the measure. So, how do I put the form together to allow this?



I started the form by adding a collection of check boxes for all the available ingredients, but this only allows the ingredient to be linked or not linked - there's no way that I know to allow additional inputs to be added here.



Here's the recipes_controller:



def new
@recipe = Recipe.new

@ingredients = Ingredient.all
end

def edit
@recipe = Recipe.find(params[:id])
@ingredients = Ingredient.all
end

def create
@recipe = Recipe.new(recipe_params)

if @recipe.save
redirect_to @recipe
else
render 'new'
end
end
...
private
def recipe_params
params.require(:recipe).permit(:name, :method, :category, ingredient_ids:)
end


And the models:



class Recipe < ApplicationRecord
has_many :measures
has_many :ingredients, through: :measures
accepts_nested_attributes_for :ingredients
end

class Measure < ApplicationRecord
belongs_to :ingredient
belongs_to :recipe
accepts_nested_attributes_for :ingredient
end

class Ingredient < ApplicationRecord
has_many :measures
has_many :recipes, through: :measures
end


And the basic Recipe form partial:



# /views/recipes/_form.html.erb
<%= form_for(@recipe) do |form| %>

<% if @recipe.errors.any? %>
<div id="error_explanation">
<h2>
<%= pluralize(@recipe.errors.count, "error") %> prohibited
this recipe from being saved:
</h2>
<ul>
<% @recipe.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>

<p>
<%= form.label :name %><br>
<%= form.text_field :name %>
</p>

<p>
<%= form.collection_check_boxes :ingredient_ids, @ingredients, :id, :name %>
</p>

<p>
<%= form.fields_for :measures do |ff| %>
<% @ingredients.each do |ingredient| %>
<%= ff.label :unit %>
<%= ff.text_field :unit %> |
<%= ff.label :quantity %>
<%= ff.text_field :quantity %> |
<%= ff.label ingredient.name %>
<%= ff.check_box :ingredient_id %>
<br>
<% end %>
<% end %>
</p>

<p>
<%= form.submit %>
</p>

<% end %>


Thanks for your help!










share|improve this question



























    0















    I'm trying to build an app for storing recipes so that I can (eventually) build shopping lists based on recipe ingredients.



    What I'm struggling with is being able to link ingredients to recipes based on their measures, i.e. a recipe could use 300 grams of flour and one pinch of salt while another recipe might use two cups of flour and one teaspoon of salt.



    I've set up the DB with three tables: Recipes, Measures and Ingredients. However I'm getting stuck trying to create the basic form elements so that I can associate the unit (e.g. grams, cups or mL) with the quantity (1 or 500) of the measure. So, how do I put the form together to allow this?



    I started the form by adding a collection of check boxes for all the available ingredients, but this only allows the ingredient to be linked or not linked - there's no way that I know to allow additional inputs to be added here.



    Here's the recipes_controller:



    def new
    @recipe = Recipe.new

    @ingredients = Ingredient.all
    end

    def edit
    @recipe = Recipe.find(params[:id])
    @ingredients = Ingredient.all
    end

    def create
    @recipe = Recipe.new(recipe_params)

    if @recipe.save
    redirect_to @recipe
    else
    render 'new'
    end
    end
    ...
    private
    def recipe_params
    params.require(:recipe).permit(:name, :method, :category, ingredient_ids:)
    end


    And the models:



    class Recipe < ApplicationRecord
    has_many :measures
    has_many :ingredients, through: :measures
    accepts_nested_attributes_for :ingredients
    end

    class Measure < ApplicationRecord
    belongs_to :ingredient
    belongs_to :recipe
    accepts_nested_attributes_for :ingredient
    end

    class Ingredient < ApplicationRecord
    has_many :measures
    has_many :recipes, through: :measures
    end


    And the basic Recipe form partial:



    # /views/recipes/_form.html.erb
    <%= form_for(@recipe) do |form| %>

    <% if @recipe.errors.any? %>
    <div id="error_explanation">
    <h2>
    <%= pluralize(@recipe.errors.count, "error") %> prohibited
    this recipe from being saved:
    </h2>
    <ul>
    <% @recipe.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
    <% end %>
    </ul>
    </div>
    <% end %>

    <p>
    <%= form.label :name %><br>
    <%= form.text_field :name %>
    </p>

    <p>
    <%= form.collection_check_boxes :ingredient_ids, @ingredients, :id, :name %>
    </p>

    <p>
    <%= form.fields_for :measures do |ff| %>
    <% @ingredients.each do |ingredient| %>
    <%= ff.label :unit %>
    <%= ff.text_field :unit %> |
    <%= ff.label :quantity %>
    <%= ff.text_field :quantity %> |
    <%= ff.label ingredient.name %>
    <%= ff.check_box :ingredient_id %>
    <br>
    <% end %>
    <% end %>
    </p>

    <p>
    <%= form.submit %>
    </p>

    <% end %>


    Thanks for your help!










    share|improve this question

























      0












      0








      0








      I'm trying to build an app for storing recipes so that I can (eventually) build shopping lists based on recipe ingredients.



      What I'm struggling with is being able to link ingredients to recipes based on their measures, i.e. a recipe could use 300 grams of flour and one pinch of salt while another recipe might use two cups of flour and one teaspoon of salt.



      I've set up the DB with three tables: Recipes, Measures and Ingredients. However I'm getting stuck trying to create the basic form elements so that I can associate the unit (e.g. grams, cups or mL) with the quantity (1 or 500) of the measure. So, how do I put the form together to allow this?



      I started the form by adding a collection of check boxes for all the available ingredients, but this only allows the ingredient to be linked or not linked - there's no way that I know to allow additional inputs to be added here.



      Here's the recipes_controller:



      def new
      @recipe = Recipe.new

      @ingredients = Ingredient.all
      end

      def edit
      @recipe = Recipe.find(params[:id])
      @ingredients = Ingredient.all
      end

      def create
      @recipe = Recipe.new(recipe_params)

      if @recipe.save
      redirect_to @recipe
      else
      render 'new'
      end
      end
      ...
      private
      def recipe_params
      params.require(:recipe).permit(:name, :method, :category, ingredient_ids:)
      end


      And the models:



      class Recipe < ApplicationRecord
      has_many :measures
      has_many :ingredients, through: :measures
      accepts_nested_attributes_for :ingredients
      end

      class Measure < ApplicationRecord
      belongs_to :ingredient
      belongs_to :recipe
      accepts_nested_attributes_for :ingredient
      end

      class Ingredient < ApplicationRecord
      has_many :measures
      has_many :recipes, through: :measures
      end


      And the basic Recipe form partial:



      # /views/recipes/_form.html.erb
      <%= form_for(@recipe) do |form| %>

      <% if @recipe.errors.any? %>
      <div id="error_explanation">
      <h2>
      <%= pluralize(@recipe.errors.count, "error") %> prohibited
      this recipe from being saved:
      </h2>
      <ul>
      <% @recipe.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
      <% end %>
      </ul>
      </div>
      <% end %>

      <p>
      <%= form.label :name %><br>
      <%= form.text_field :name %>
      </p>

      <p>
      <%= form.collection_check_boxes :ingredient_ids, @ingredients, :id, :name %>
      </p>

      <p>
      <%= form.fields_for :measures do |ff| %>
      <% @ingredients.each do |ingredient| %>
      <%= ff.label :unit %>
      <%= ff.text_field :unit %> |
      <%= ff.label :quantity %>
      <%= ff.text_field :quantity %> |
      <%= ff.label ingredient.name %>
      <%= ff.check_box :ingredient_id %>
      <br>
      <% end %>
      <% end %>
      </p>

      <p>
      <%= form.submit %>
      </p>

      <% end %>


      Thanks for your help!










      share|improve this question














      I'm trying to build an app for storing recipes so that I can (eventually) build shopping lists based on recipe ingredients.



      What I'm struggling with is being able to link ingredients to recipes based on their measures, i.e. a recipe could use 300 grams of flour and one pinch of salt while another recipe might use two cups of flour and one teaspoon of salt.



      I've set up the DB with three tables: Recipes, Measures and Ingredients. However I'm getting stuck trying to create the basic form elements so that I can associate the unit (e.g. grams, cups or mL) with the quantity (1 or 500) of the measure. So, how do I put the form together to allow this?



      I started the form by adding a collection of check boxes for all the available ingredients, but this only allows the ingredient to be linked or not linked - there's no way that I know to allow additional inputs to be added here.



      Here's the recipes_controller:



      def new
      @recipe = Recipe.new

      @ingredients = Ingredient.all
      end

      def edit
      @recipe = Recipe.find(params[:id])
      @ingredients = Ingredient.all
      end

      def create
      @recipe = Recipe.new(recipe_params)

      if @recipe.save
      redirect_to @recipe
      else
      render 'new'
      end
      end
      ...
      private
      def recipe_params
      params.require(:recipe).permit(:name, :method, :category, ingredient_ids:)
      end


      And the models:



      class Recipe < ApplicationRecord
      has_many :measures
      has_many :ingredients, through: :measures
      accepts_nested_attributes_for :ingredients
      end

      class Measure < ApplicationRecord
      belongs_to :ingredient
      belongs_to :recipe
      accepts_nested_attributes_for :ingredient
      end

      class Ingredient < ApplicationRecord
      has_many :measures
      has_many :recipes, through: :measures
      end


      And the basic Recipe form partial:



      # /views/recipes/_form.html.erb
      <%= form_for(@recipe) do |form| %>

      <% if @recipe.errors.any? %>
      <div id="error_explanation">
      <h2>
      <%= pluralize(@recipe.errors.count, "error") %> prohibited
      this recipe from being saved:
      </h2>
      <ul>
      <% @recipe.errors.full_messages.each do |msg| %>
      <li><%= msg %></li>
      <% end %>
      </ul>
      </div>
      <% end %>

      <p>
      <%= form.label :name %><br>
      <%= form.text_field :name %>
      </p>

      <p>
      <%= form.collection_check_boxes :ingredient_ids, @ingredients, :id, :name %>
      </p>

      <p>
      <%= form.fields_for :measures do |ff| %>
      <% @ingredients.each do |ingredient| %>
      <%= ff.label :unit %>
      <%= ff.text_field :unit %> |
      <%= ff.label :quantity %>
      <%= ff.text_field :quantity %> |
      <%= ff.label ingredient.name %>
      <%= ff.check_box :ingredient_id %>
      <br>
      <% end %>
      <% end %>
      </p>

      <p>
      <%= form.submit %>
      </p>

      <% end %>


      Thanks for your help!







      forms ruby-on-rails-5 has-many-through






      share|improve this question













      share|improve this question











      share|improve this question




      share|improve this question










      asked Jan 2 at 22:50









      Cat BurstonCat Burston

      378138




      378138
























          0






          active

          oldest

          votes












          Your Answer






          StackExchange.ifUsing("editor", function () {
          StackExchange.using("externalEditor", function () {
          StackExchange.using("snippets", function () {
          StackExchange.snippets.init();
          });
          });
          }, "code-snippets");

          StackExchange.ready(function() {
          var channelOptions = {
          tags: "".split(" "),
          id: "1"
          };
          initTagRenderer("".split(" "), "".split(" "), channelOptions);

          StackExchange.using("externalEditor", function() {
          // Have to fire editor after snippets, if snippets enabled
          if (StackExchange.settings.snippets.snippetsEnabled) {
          StackExchange.using("snippets", function() {
          createEditor();
          });
          }
          else {
          createEditor();
          }
          });

          function createEditor() {
          StackExchange.prepareEditor({
          heartbeatType: 'answer',
          autoActivateHeartbeat: false,
          convertImagesToLinks: true,
          noModals: true,
          showLowRepImageUploadWarning: true,
          reputationToPostImages: 10,
          bindNavPrevention: true,
          postfix: "",
          imageUploader: {
          brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
          contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
          allowUrls: true
          },
          onDemand: true,
          discardSelector: ".discard-answer"
          ,immediatelyShowMarkdownHelp:true
          });


          }
          });














          draft saved

          draft discarded


















          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54014195%2frails-has-many-through-form-adding-variables-to-joining-table%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown

























          0






          active

          oldest

          votes








          0






          active

          oldest

          votes









          active

          oldest

          votes






          active

          oldest

          votes
















          draft saved

          draft discarded




















































          Thanks for contributing an answer to Stack Overflow!


          • Please be sure to answer the question. Provide details and share your research!

          But avoid



          • Asking for help, clarification, or responding to other answers.

          • Making statements based on opinion; back them up with references or personal experience.


          To learn more, see our tips on writing great answers.




          draft saved


          draft discarded














          StackExchange.ready(
          function () {
          StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f54014195%2frails-has-many-through-form-adding-variables-to-joining-table%23new-answer', 'question_page');
          }
          );

          Post as a guest















          Required, but never shown





















































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown

































          Required, but never shown














          Required, but never shown












          Required, but never shown







          Required, but never shown







          Popular posts from this blog

          MongoDB - Not Authorized To Execute Command

          in spring boot 2.1 many test slices are not allowed anymore due to multiple @BootstrapWith

          How to fix TextFormField cause rebuild widget in Flutter