I tried several methods I found online but none worked and they weren't specifically targeting the problems I'm having. Basically I have a recipes Rails app, and using Angular, I have to:
(1) Allow the user to add one or more ingredients and directions in the form, like this: http://jsfiddle.net/V4BqE/
(2) Save the ingredients and directions as an array data type in the Rails database (I'm using postgresql), sort of like this but without using $scope: How to create an Array with AngularJS's ng-model
Schema:
create_table "recipes", force: :cascade do |t|
t.string "title"
t.integer "difficulty"
t.integer "time"
t.integer "servings"
t.string "description"
t.string "ingredients", array: true
t.string "directions", array: true
t.integer "category_id"
t.integer "author_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Controller:
(function() {
'use strict';
function NewRecipeController ($location, RecipeService, CategoryService) {
var vm = this;
CategoryService.getCategories()
.then(function(response) {
vm.categories = response.data;
});
vm.addRecipe = function() {
var data = {
title: this.title,
difficulty: this.difficulty,
time: this.time,
servings: this.servings,
description: this.description,
// Im stuck trying to figure out the following 2 lines
ingredients: this.ingredients,
directions: this.directions,
category_id: this.category.id
};
RecipeService.createRecipe(data);
$location.path('profile');
};
}
angular
.module('app')
.controller('NewRecipeController', NewRecipeController)
}());
Form (just the ingredients and directions section are relevant):
<form name="newRecipe" novalidate ng-submit="vm.addRecipe()">
<!-- title -->
<div class="form-group">
<label for="title">Recipe Name</label>
<input class="form-control" type="text" name="title" ng-model="vm.title" required>
</div>
<!-- category -->
<div class="form-group">
<label for="category">Category</label>
<select class="form-control" name="category" ng-model="vm.category" ng-options="category.name for category in vm.categories" required></select>
</div>
<!-- description -->
<div class="form-group">
<label for="description">Description</label>
<input class="form-control" type="text" name="description" ng-model="vm.description" required>
</div>
<!-- difficulty -->
<div class="form-group">
<label for="difficulty">Difficulty</label>
<input class="form-control" type="number" name="difficulty" ng-model="vm.difficulty" min="1" max="5" required>
<small id="emailHelp" class="form-text text-muted">Enter a number between 1 and 5.</small>
</div>
<!-- time -->
<div class="form-group">
<label for="time">Time to Make (Minutes)</label>
<input class="form-control" type="number" name="time" ng-model="vm.time" min="5" step="5" required>
<small id="emailHelp" class="form-text text-muted">Enter a number that is an increment of 5 minutes.</small>
</div>
<!-- servings -->
<div class="form-group">
<label for="servings">Servings</label>
<input class="form-control" type="number" name="servings" ng-model="vm.servings" required>
</div>
<!-- ingredients - this is where I'm stuck -->
<!-- I want to be able to let the user add more input fields if they want and do the same for directions -->
<div class="form-group" ng-repeat="ingredient in vm.ingredients">
<label for="ingredients">Ingredients</label>
<input class="form-control" type="text" name="ingredients" ng-model="vm.ingredients[$index]" required>
</div>
<div ng-show="newRecipe.$valid">
<input class="btn btn-primary" type="submit" value="Create Recipe">
</div>
</form>
I understand that I have to save the array as a string. I tried directly saving ingredients: '["ingredient1", "ingredient2"]'
and ingredients: '["ingredient1, ingredient2"]'
, but both just saved as ingredients: ["ingredient1"]
. I've also tried JSON.stringify(ingredients)
. I am using a serializer:
class RecipeSerializer < ActiveModel::Serializer
attributes :id, :title, :difficulty, :time, :servings, :description, :ingredients, :directions
belongs_to :category
belongs_to :author, class_name: 'User'
# has_many :favorites
has_many :favorited_users, through: :favorites, source: :user
end
Recipe Rails controller #create:
def create
@recipe = Recipe.new(recipe_params)
@recipe.author = current_user
@recipe.save
end
Full code on Github: https://github.com/auranbuckles/world-recipes
serialize :ingredients, Array
andserialize :directions, Array
. Also track down the Rails controller that this is being submitted to; there should be a method that extracts the recipe params before it's saved; that'd also be useful for debugging this. – guiniveretoo 19 hours agoingredients: '["ingredient1", "ingredient2"]
if the Rails model and controller are set up correctly, that's why I'm asking to see those too) – guiniveretoo 19 hours agoserialize :ingredients, Array
in the model. In this case, if I sendingredients: '["ingredient1", "ingredient2"]'
to the backend, I get the errorActiveRecord::SerializationTypeMismatch in RecipesController#create
Attribute was supposed to be a Array, but was a String. -- "[\"ingredient1\", \"ingredient2\"]"
. And if I send a plain arrayingredients: ["ingredient1", "ingredient2"]
I get a blank [] array sent to the backend. I'm still stuck but I'll keep testing this out. – Auran Buckles 8 hours ago