数据库保存问题 Vue.js 和 Rails

Posted

技术标签:

【中文标题】数据库保存问题 Vue.js 和 Rails【英文标题】:Database Saving Issue Vue.js and Rails 【发布时间】:2017-06-22 15:58:51 【问题描述】:

我正在尝试在 Rails 应用程序中使用 Vue.js 创建嵌套表单。我正在使用嵌套表单将配料保存到食谱中。现在成分中的所有内容都保存了,但成分的名称(从输入字段中获取)。如何获取此名称字段以保存在数据库中?

app/models/ingredient.rb

class Ingredient < ApplicationRecord
  belongs_to :recipe
end

app/models/recipe.rb

class Recipe < ApplicationRecord
  has_many :ingredients
end

app/views/index.html.erb

<h1>Index</h1>
<div id="app">
   message 
  <form>
    <div class="form-group">
      <label class="form-label">Name</label>
      <input class="form-control" type="text" placeholder="Recipe's Name" v-model="recipe.name">
    </div>
    <div class="form-group">
      <label class="form-label">Chef</label>
      <input class="form-control" type="text" placeholder="Chef's Name" v-model="recipe.chef">
    </div>
    <div class="form-group">
      <label class="form-label">Cooktime</label>
      <select class="form-control" type="text" v-model="recipe.cooktime">
        <option v-for="cookingtime in cookingtimes" :value="cookingtime.value">
           cookingtime.cook 
        </option>
      </select>
    </div>
    <div class="form-group">
      <label class="form-label">Serves</label>
      <select class="form-control" type="text" v-model="recipe.amount">
        <option v-for="serving in servings" :value="serving.value">
           serving.serves 
        </option>
      </select>
    </div>
    <div class="form-group">
      <label class="form-label">Description</label>
      <textarea class="form-control" rows="5" placeholder="Recipe Description" v-model="recipe.description"></textarea>
    </div>
    <div class="form-group">
      <label class="form-label">Favorite</label>
      <input type="checkbox" v-model="recipe.favorite">
    </div>

    <button class="btn btn-default" type="button" @click="newIngredient">Add Ingredient</button>
    <div class="form-group" v-for="(ingredient, index) in recipe.ingredients">
      <label class="form-label">Ingredient</label>
      <input type="text" v-model="ingredient.name">
      <a @click="removeIngredient(index)">Remove Ingredient</a>
      <p>Ingredient:  ingredient </p>
      <p>Index:  index </p>
    </div>

    <div id="recipe-index-submit-button-container">
      <button type="submit" class="btn btn-default" @click="newRecipe">Submit</button>
    </div>
  </form>
</div>

app/views/api/v1/recipes/index.json.jbuilder

json.array! @recipes, partial: "recipe", as: :recipe

app/views/api/v1/recipes/_recipe.json.jbuilder

json.id recipe.id
json.name recipe.name
json.chef recipe.chef
json.cooktime recipe.cooktime
json.amount recipe.amount
json.description recipe.description
json.favorite recipe.favorite
json.user_id recipe.user_id

json.ingredients do 
  json.array!(recipe.ingredients) do |ingredient|
    json.ingredient_id ingredient.id
    json.ingredient_name ingredient.name
    json.ingredient_recipe_id ingredient.recipe_id
  end
end

app/controllers/api/v1/recipes_controller.rb

class Api::V1::RecipesController < ApplicationController
  def index
    @recipes = Recipe.all
  end

  def create
    @recipe = Recipe.new(recipe_params)
    @recipe.ingredients.build

    if @recipe.save
      render :show
    else
      render json:  errors: @recipe.errors.full_messages , status: 422
    end
  end

  def show
    @recipe = Recipe.find_by(id: params[:id])
  end

  private

    def recipe_params
      params.require(:recipe).permit(
        :name,
        :chef,
        :cooktime,
        :amount,
        :description,
        :favorite,
        :user_id,
        ingredients:[
          :id,
          :name,
          :recipe_id
        ]
      )
    end
end

app/javascripts/recipes_ctrl.js

$(document).on('ready', function() 
  new Vue(
    el: '#app',
    data: 
      message: "Hello World!",
      recipe: 
        name: '',
        chef: '',
        cooktime: '',
        amount: '',
        description: '',
        favorite: false,
        ingredients: [
          name: '',
        ]
      ,
      recipes: [],
      errors: ,
      cookingtimes: [
        cook: "less than 15 minutes", value: "less than 15 minutes",
        cook: "15 minutes", value: "15 minutes",
        cook: "30 minutes", value: "30 minutes",
        cook: "45 minutes", value: "45 minutes",
        cook: "1 hour", value: "1 hour",
        cook: "1 hour 30 minutes", value: "1 hour 30 minutes",
        cook: "2 hours", value: "2 hours",
        cook: "2 hours 30 minutes", value: "2 hours 30 minutes",
        cook: "3 hours", value: "3 hours",
        cook: "3 hours 30 minutes", value: "3 hours 30 minutes",
        cook: "4 hours", value: "4 hours",
        cook: "more than 4 hours", value: "more than 4 hours"
      ],
      servings: [
        serves: "1", value: 1,
        serves: "2", value: 2,
        serves: "3", value: 3,
        serves: "4", value: 4,
        serves: "5", value: 5,
        serves: "6", value: 6,
        serves: "7", value: 7,
        serves: "8", value: 8,
        serves: "9", value: 9,
        serves: "10", value: 10,
        serves: "11", value: 11,
        serves: "12", value: 12,
        serves: "more than 12", value: "more than 12"
      ]
    ,
    methods: 
      newRecipe: function()
        this.$http.post('/api/v1/recipes.json', this.recipe).then(function(response)
            this.recipes.push(this.recipe);

        ).catch(function(response)
          this.errors = response.data.errors;
        );
        console.log("this.recipe " + this.recipe);
      ,
      newIngredient: function()
        this.recipe.ingredients.push(name:'', recipe_id: '');
      ,
      removeIngredient: function(index)
        console.log("index " + index);
        this.recipe.ingredients.splice(index, 1);
      
    
  )
)

这是终端显示给我的。我现在也确实将我的应用程序控制器设置为空会话。

Processing by Api::V1::RecipesController#create as JSON
  Parameters: "name"=>"", "chef"=>"", "cooktime"=>"", "amount"=>"", "description"=>"", "favorite"=>false, "ingredients"=>["name"=>"test", "recipe_id"=>""], "recipe"=>"name"=>"", "chef"=>"", "cooktime"=>"", "amount"=>"", "description"=>"", "favorite"=>false
Can't verify CSRF token authenticity.
   (4.3ms)  BEGIN
  SQL (5.5ms)  INSERT INTO "recipes" ("name", "chef", "cooktime", "description", "favorite", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7) RETURNING "id"  [["name", ""], ["chef", ""], ["cooktime", ""], ["description", ""], ["favorite", false], ["created_at", 2017-02-05 17:29:34 UTC], ["updated_at", 2017-02-05 17:29:34 UTC]]
  SQL (51.5ms)  INSERT INTO "ingredients" ("recipe_id", "created_at", "updated_at") VALUES ($1, $2, $3) RETURNING "id"  [["recipe_id", 18], ["created_at", 2017-02-05 17:29:34 UTC], ["updated_at", 2017-02-05 17:29:34 UTC]]
   (3.1ms)  COMMIT
  Rendering api/v1/recipes/show.json.jbuilder
  Ingredient Load (0.7ms)  SELECT "ingredients".* FROM "ingredients" WHERE "ingredients"."recipe_id" = $1  [["recipe_id", 18]]
  Rendered api/v1/recipes/_recipe.json.jbuilder (12.2ms)

【问题讨论】:

【参考方案1】:

我认为您在create 操作中不需要@recipe.ingredients.build,并且以这种方式保存您需要将accepts_nested_attributes_for :ingredients 添加到Recipe

【讨论】:

以上是关于数据库保存问题 Vue.js 和 Rails的主要内容,如果未能解决你的问题,请参考以下文章

Ruby on Rails 5.1 和 Vue.js 2.4.x – 使用 Karma、Jasmine 进行测试 – 如何安装?

将 Vue.js 添加到 Rails 5.1 和 Mocha 中的单元测试不起作用

Rails - 如何使用 webpack 删除 vue.js

在 Laravel 5.1 和 Vue JS 中保存多个数据动态表单

使用表单的响应将数据集属性保存在 JSON 文件中 (Vue.js)

Vue js 2 *私下*保存组件的数据