How to create a form that would create a "User", a "Sandwich", a join table "SandwichIngredient", on the "Restaurant" show page?

时间:2019-04-16 22:30:16

标签: ruby-on-rails ruby

I have 6 modules (1. ingredients; 2. restaurants; 3. sandwich_ingredients; 4. sandwiches; 5. stocks; 6. users) and the user should be able to create/personalise a sandwich using the ingredients of that specific restaurant. Therefore, I would like to create a form on the show.html.erb of the restaurant so that the user can pick up several ingredients and create their own sandwich.

I feel comfortable working with 3 modules in a many-to-many relationship but with 6 tables I just get confused and lost.

I tried form_for, form_tag, collection_check_boxes. When I used to work with a smaller project, I had no issues but now I'm not sure what approach should I take. I tried to create the form on the user show page first and then on the sandwich show page but it didn't seem quite right.

This is the code from the restaurant show.html.erb page:

<ul>
<%= form_tag('/restaurants/create_sandwich') do %>
<%= label_tag 'Ingredients' %>
  <li><%= collection_check_boxes(:ingredient, :id, @restaurant.ingredients, :id, :name) %></li>
  <%= submit_tag 'Create' %>
<% end %>
</ul>

The restaurants_controller.rb (messed up):

class RestaurantsController < ApplicationController
  def index
    @restaurants = Restaurant.all
  end

  def show
    @restaurant = Restaurant.find(params[:id])
    @user = User.new
    @sandwich = Sandwich.new
  end
  def new
    @sandwich = Sandwich.new
    # res = Restaurant.find(params[:id])
    # @restaurant_ingredients = res.ingredients
  end

  def select_ingredients
    # byebug
    #
    # @restaurant_ingredients = Restaurant.find(params[:id]).ingredients
    # byebug
    # @restaurant_ingredients = res.ingredients
    # @ingredients = Ingredient.all

  end

  def create_sandwich
    # byebug
    @user = User.find_or_create_by({name: params[:user_name]})
    @sandwich = Sandwich.new({name: params[:recipe_name], user_id: @user.id})
    @sandwich.sandwich_ingredient_ids = params[:ingredients]
    if @sandwich.save
      redirect_to sandwich_path(@sandwich)
    else
      render :new
    end

  end

  def edit
    #code
  end

  def update
    #code
  end

  def delete
    #code
  end


end

If it can help, these are the routes:

Rails.application.routes.draw do
  # get '/restaurants/:id', to: 'restaurants#create_sandwich'
  post '/restaurants/create_sandwich', to: 'restaurants#create_sandwich'
  resources :stocks
  resources :restaurants
  resources :sandwich_ingredients
  resources :ingredients
  resources :sandwiches
  resources :users
  # For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
end

and this is my schema:

ActiveRecord::Schema.define(version: 2019_04_15_174308) do

  create_table "ingredients", force: :cascade do |t|
    t.string "name"
    t.integer "quantity"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "restaurants", force: :cascade do |t|
    t.string "name"
    t.string "location"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "sandwich_ingredients", force: :cascade do |t|
    t.integer "sandwich_id"
    t.integer "ingredient_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "sandwiches", force: :cascade do |t|
    t.string "name"
    t.integer "user_id"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "stocks", force: :cascade do |t|
    t.integer "restaurant_id"
    t.integer "ingredient_id"
    t.integer "count"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "users", force: :cascade do |t|
    t.string "name"
    t.string "surname"
    t.string "email"
    t.string "phone_number"
    t.integer "age"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

end

What I'm trying to achieve is a form that would create the association "SandwichIngredient" and to do so, the "User" and the "Sandwich" but at this point I feel just lost.

1 个答案:

答案 0 :(得分:1)

Lots of areas to comment on here, and the question is quite vague but I'll give some tips

  1. Your 'new' action on your restaurant controller should be for a new restaurant, not a new sandwich.

  2. Your 'new sandwich' form should probably be directing to the create action on your sandwiches controller. You're trying to do too much on the restaurants controller.

  3. If your ingredients belong to a restaurant, they need a restaurant_id field

  4. You probably don't want to create a new user each time you create a sandwich, perhaps you want to add devise or a similar user management gem to your project and have them sign in, and assign the sandwich to the current user, or have a drop down select of the users in the system as part of the sandwich form

  5. As a general tip, I would completely ignore your stocks model for now, focus on getting sandwiches working first.

  6. Not super related but would be good to have either one 'name' field for a user or 'first_name' and 'last_name' to avoid confusion

  7. You may need to add a hidden field in the form to contain the restaurant_id to be able to pass this value through when you submit the form

  8. Make sure you have a field on the sandwich form for the name of the sandwich

  9. I would probably recommend sticking with 'form_for' for @sandwich, which by default should go to the sandwiches create action as mentioned above.


Feel free to post a link to this project on github or similar if you need further help.