Why is ecto raising Ecto.NoPrimaryKeyValueError when I have a primary key and it has a value? - ecto

Whenever I run this code:
{:ok, act_1} = %Kempelen.Models.GameAct{}
|> Kempelen.Models.GameAct.changeset(%{
game_play: place_road,
game_player: player_1,
game_round: round_1
})
|> Kempelen.Database.Repo.insert
I'm getting this exception:
** (Ecto.NoPrimaryKeyValueError) struct `%Kempelen.Models.GamePlayer{__meta__: #Ecto.Schema.Metadata<:loaded, "game_players">, account: %Kempelen.Models.Account{__meta__: #Ecto.Schema.Metadata<:loaded, "accounts">, email: "kurtis#difference-engineers.org", game_players: #Ecto.Association.NotLoaded<association :game_players is not loaded>, game_rounds: #Ecto.Association.NotLoaded<association :game_rounds is not loaded>, game_tables: #Ecto.Association.NotLoaded<association :game_tables is not loaded>, id: "65880220-e39b-450d-ba7f-0642bea8dbc8", inserted_at: ~N[2020-02-16 16:15:33], name: nil, onboarding_state: "converted", organization_memberships: #Ecto.Association.NotLoaded<association :organization_memberships is not loaded>, organizations: #Ecto.Association.NotLoaded<association :organizations is not loaded>, password: nil, password_hash: nil, role_state: "user", unconfirmed_email: "kurtis#difference-engineers.org", updated_at: ~N[2020-02-16 16:15:33], username: nil}, account_id: "65880220-e39b-450d-ba7f-0642bea8dbc8", game_acts: #Ecto.Association.NotLoaded<association :game_acts is not loaded>, game_robot: nil, game_robot_id: nil, game_table: %Kempelen.Models.GameTable{__meta__: #Ecto.Schema.Metadata<:loaded, "game_tables">, game: %Kempelen.Models.Game{__meta__: #Ecto.Schema.Metadata<:loaded, "games">, game_plays: #Ecto.Association.NotLoaded<association :game_plays is not loaded>, game_tables: #Ecto.Association.NotLoaded<association :game_tables is not loaded>, id: "31eee3b8-b43c-411a-8528-479269c63d2d", inserted_at: ~N[2020-02-16 16:15:33], name: "Settlers of Catan", organization: %Kempelen.Models.Organization{__meta__: #Ecto.Schema.Metadata<:loaded, "organizations">, accounts: #Ecto.Association.NotLoaded<association :accounts is not loaded>, games: #Ecto.Association.NotLoaded<association :games is not loaded>, id: "3311c337-f480-4292-9582-c45f249730b2", inserted_at: ~N[2020-02-16 16:15:32], name: "Hasbro", organization_memberships: #Ecto.Association.NotLoaded<association :organization_memberships is not loaded>, robots: #Ecto.Association.NotLoaded<association :robots is not loaded>, slug: "hasbro", updated_at: ~N[2020-02-16 16:15:32]}, organization_id: "3311c337-f480-4292-9582-c45f249730b2", slug: "settlers-of-catan", updated_at: ~N[2020-02-16 16:15:33]}, game_id: "31eee3b8-b43c-411a-8528-479269c63d2d", game_players: #Ecto.Association.NotLoaded<association :game_players is not loaded>, game_rounds: #Ecto.Association.NotLoaded<association :game_rounds is not loaded>, id: "2cda5e3c-c57d-4117-a541-0c6a409984b6", inserted_at: ~N[2020-02-16 16:15:33], name: "FFA", slug: "ffa", updated_at: ~N[2020-02-16 16:15:33]}, game_table_id: "2cda5e3c-c57d-4117-a541-0c6a409984b6", host: true, id: "591227e6-3ea0-4f3f-8a44-471d7073c2df", inserted_at: ~N[2020-02-16 16:15:33], name: "Kurtis", slug: "kurtis", updated_at: ~N[2020-02-16 16:15:33]}` is missing primary key value
Here's are the models:
defmodule Kempelen.Models.GameAct do
use Ecto.Schema
import Ecto.Changeset
#primary_key {:id, :binary_id, autogenerate: true}
#foreign_key_type :binary_id
schema "game_acts" do
belongs_to :game_play, Kempelen.Models.GamePlay, primary_key: true
belongs_to :game_player, Kempelen.Models.GamePlayer, primary_key: true
belongs_to :game_round, Kempelen.Models.GameRound, primary_key: true
timestamps()
end
#doc false
def changeset(%{} = record, attributes \\ %{}) do
record
|> cast(attributes, [])
|> validate_required([])
|> assoc_constraint(:game_play)
|> assoc_constraint(:game_player)
|> assoc_constraint(:game_round)
|> put_assoc(:game_play, attributes.game_play)
|> put_assoc(:game_player, attributes.game_player)
|> put_assoc(:game_round, attributes.game_round)
end
end
defmodule Kempelen.Models.GamePlayer do
use Ecto.Schema
import Ecto.Changeset
#primary_key {:id, :binary_id, autogenerate: true}
#foreign_key_type :binary_id
schema "game_players" do
field :name, :string
field :slug, Kempelen.Slugs.Name.Type
field :host, :boolean, default: false
belongs_to :game_table, Kempelen.Models.GameTable, primary_key: true
belongs_to :account, Kempelen.Models.Account, primary_key: true
belongs_to :game_robot, Kempelen.Models.GameRobot, primary_key: true
has_many :game_acts, Kempelen.Models.GameAct
timestamps()
end
#doc false
def changeset(%{} = record, attributes \\ %{}) do
record
|> cast(attributes, [:name, :host])
|> validate_required([:name, :host])
|> assoc_constraint(:game_table)
|> assoc_constraint(:account)
|> assoc_constraint(:game_robot)
|> Kempelen.Slugs.Name.maybe_generate_slug
|> Kempelen.Slugs.Name.unique_constraint
|> put_assoc(:game_robot, attributes[:game_robot])
|> put_assoc(:account, attributes[:account])
|> put_assoc(:game_table, attributes.game_table)
end
end
It's not just the game_play model either, it also happens of the game_player.
The changeset appears to think it's valid, as well:
#Ecto.Changeset<
action: nil,
changes: %{
game_play: #Ecto.Changeset<action: :update, changes: %{}, errors: [],
data: #Kempelen.Models.GamePlay<>, valid?: true>,
game_player: #Ecto.Changeset<action: :update, changes: %{}, errors: [],
data: #Kempelen.Models.GamePlayer<>, valid?: true>,
game_round: #Ecto.Changeset<action: :update, changes: %{}, errors: [],
data: #Kempelen.Models.GameRound<>, valid?: true>
},
errors: [],
data: #Kempelen.Models.GameAct<>,
valid?: true
>

Alright, so I finally figured it out. It turns out that while I wanted the account and game_robot relationships to be optional (one or the other, in business logic), the primary_key: true option for belongs_to in the schema means that the foreign key column must have a value.

Related

How to fix this error? Failed validating 'oneOf' in schema

I am creating an API using Flask, Connexion and SQLAlchemy to access a database. To do this I needed the following dependencies:
Flask-SQLAlchemy
Flask-Marshmallow
Marshmallow-SQLAlchemy
Marshmallow
When I run the file with the app instance using the command python3 <filename>, this is the error produced:
Traceback (most recent call last):
File "server.py", line 16, in <module>
connex_app.add_api("swagger.yml")
File "/home/fidelis/repo/proj4/env/lib/python3.6/site-packages/connexion/apps/flask_app.py", line 57, in add_api
api = super(FlaskApp, self).add_api(specification, **kwargs)
File "/home/fidelis/repo/proj4/env/lib/python3.6/site-packages/connexion/apps/abstract.py", line 153, in add_api
options=api_options.as_dict())
File "/home/fidelis/repo/proj4/env/lib/python3.6/site-packages/connexion/apis/abstract.py", line 75, in __init__
self.specification = Specification.load(specification, arguments=arguments)
File "/home/fidelis/repo/proj4/env/lib/python3.6/site-packages/connexion/spec.py", line 153, in load
return cls.from_file(spec, arguments=arguments)
File "/home/fidelis/repo/proj4/env/lib/python3.6/site-packages/connexion/spec.py", line 107, in from_file
return cls.from_dict(spec)
File "/home/fidelis/repo/proj4/env/lib/python3.6/site-packages/connexion/spec.py", line 144, in from_dict
return Swagger2Specification(spec)
File "/home/fidelis/repo/proj4/env/lib/python3.6/site-packages/connexion/spec.py", line 38, in __init__
self._validate_spec(raw_spec)
File "/home/fidelis/repo/proj4/env/lib/python3.6/site-packages/connexion/spec.py", line 214, in _validate_spec
raise InvalidSpecification.create_from(e)
connexion.exceptions.InvalidSpecification: None is not valid under any of the given schemas
Failed validating 'oneOf' in schema['properties']['paths']['patternProperties']['^/']['properties']['delete']['properties']['responses']['patternProperties']['^([0-9]{3})$|^(default)$']:
{'oneOf': [{'$ref': '#/definitions/response'},
{'$ref': '#/definitions/jsonReference'}]}
On instance['paths']['/people/{person_id}']['delete']['responses']['200']:
Below is the swagger.yml file:
swagger: "2.0"
info:
description: This is the swagger file that goes with our server code
version: "1.0.0"
title: Swagger Rest Article
consumes:
- application/json
produces:
- application/json
basePath: /api
# Paths supported by the server application
paths:
/people:
get:
operationId: people.read_all
tags:
- People
summary: Read the entire set of people, sorted by last name
description: Read the entire set of people, sorted by last name
responses:
200:
description: Successfully read people set operation
schema:
type: array
items:
properties:
person_id:
type: string
description: Id of the person
fname:
type: string
description: First name of the person
lname:
type: string
description: Last name of the person
timestamp:
type: string
description: Creation/Update timestamp of the person
post:
operationId: people.create
tags:
- People
summary: Create a person
description: Create a new person
parameters:
- name: person
in: body
description: Person to create
required: True
schema:
type: object
properties:
fname:
type: string
description: First name of person to create
lname:
type: string
description: Last name of person to create
responses:
201:
description: Successfully created person
schema:
properties:
person_id:
type: string
description: Id of the person
fname:
type: string
description: First name of the person
lname:
type: string
description: Last name of the person
timestamp:
type: string
description: Creation/Update timestamp of the person record
/people/{person_id}:
get:
operationId: people.read_one
tags:
- People
summary: Read one person
description: Read one person
parameters:
- name: person_id
in: path
description: Id of the person to get
type: integer
required: True
responses:
200:
description: Successfully read person from people data operation
schema:
type: object
properties:
person_id:
type: string
description: Id of the person
fname:
type: string
description: First name of the person
lname:
type: string
description: Last name of the person
timestamp:
type: string
description: Creation/Update timestamp of the person record
put:
operationId: people.update
tags:
- People
summary: Update a person
description: Update a person
parameters:
- name: person_id
in: path
description: Id the person to update
type: integer
required: True
- name: person
in: body
schema:
type: object
properties:
fname:
type: string
description: First name of the person
lname:
type: string
description: Last name of the person
responses:
200:
description: Successfully updated person
schema:
properties:
person_id:
type: string
description: Id of the person in the database
fname:
type: string
description: First name of the person
lname:
type: string
description: Last name of the person
timestamp:
type: string
description: Creation/Update timestamp of the person record
delete:
operationId: people.delete
tags:
- People
summary: Delete a person from the people list
description: Delete a person
parameters:
- name: person_id
in: path
type: integer
description: Id of the person to delete
required: true
responses:
200:
I can't figure out how to solve the error.
I forgot to include the description right below the delete response 200.This is the line i had forgotten.
description: successfully deleted a person

How to group stream of Map to Map<String, Map<String, String>>?

I have stream of Map [name:name1, type:type1, desc:desc1, ordinal:1]. How to convert/group (with Groovy) to Map>: Map(type1: Map (neme:name1, desc:desc1, ordinal:1)).
Stream of Map
[name:productName, type:IN, ordinal:1, description:desc]
[name:productName1, type:IN, ordinal:2, description:desc]
[name:productName2, type:OUT, ordinal:3, description:desc]
and I have get: Map:
IN: Map[
[name:productName, type:IN, ordinal:1, description:desc.],
[name:productName1, type:IN, ordinal:2, description:desc.]]
OUT: Map[
[name:productName2, type:OUT, ordinal:3, description:desc.]]
You can use Stream.collect() method with Collectors.groupingBy { it.type } to collect all elements as map of type key and value of list of elements. Consider the following example:
import java.util.stream.Collectors
import java.util.stream.Stream
def input = Stream.of(
[name: 'productName', type: 'IN', ordinal: 1, description: 'desc'],
[name: 'productName1', type: 'IN', ordinal: 2, description: 'desc'],
[name: 'productName2', type: 'OUT', ordinal: 3, description: 'desc'],
)
def result = input.collect(Collectors.groupingBy { it.type })
result.each { println it }
Output:
IN=[{name=productName, type=IN, ordinal=1, description=desc}, {name=productName1, type=IN, ordinal=2, description=desc}]
OUT=[{name=productName2, type=OUT, ordinal=3, description=desc}]
Alternatively, if your input is not a Stream but a List, you could use good old Groovy Collection.groupBy() that does the same effect:
def input2 = [[name: 'productName', type: 'IN', ordinal: 1, description: 'desc'],
[name: 'productName1', type: 'IN', ordinal: 2, description: 'desc'],
[name: 'productName2', type: 'OUT', ordinal: 3, description: 'desc']]
def result2 = input2.groupBy { it.type }
result2.each { println it }

Building Flasgger/Swagger API in python3 exception

I am building a Flasgger/Swagger API in python. When I input the values into the parameters and execute the code I am seeing the following error. I have also share exception images.
"""Example endpoint returning a list of colors by value
This is using docstrings for specifications.
---
tags:
- Iris Prediction API Input values
parameters:
- name: s_length
in: path
type: string
required: true
default:
- name: s_width
in: path
type: string
required: true
default:
- name: p_length
in: path
type: string
required: true
default:
- name: p_width
in: path
type: string
required: true
default:
definitions:
value:
type: object
properties:
value_name:
type: string
items:
$ref: '#/definitions/Color'
Color:
type: string
responses:
200:
value: prediction details
schema:
$ref: '#/definitions/value'
examples:
rgb: ['red', 'green', 'blue']
"""
ValueError: Input contains NaN, infinity or a value too large for dtype('float32')
Flasgger Localhost image
Exception Image
I was able to figure it out by changing these parameters.
in: query
type: integer

Second if statement in jade layout not working

The first if statement is firing corretly and marking the checkbox as checked when the value is true, but the second isn't.
- var profileVal = false
- var logbookVal = false
div.form-group.col-md-6
-if(user.profilePublic){
- profileVal = true
-}
label Public profile
p Would you like your profile to be public?
input(type='checkbox',name='userPublicProfile',class='floatLeftCheckbox',checked=profileVal)
div.form-group.col-md-6.clearfix
label Public logbook
p Would you like your logbook to be public?
-if(user.logPublic){
- logbookVal = true
-}
input(type='checkbox',name='userPublicLogbook',class='floatLeftCheckbox',checked=logbookVal)
Both are set to Boolean in mongoDB. Both are correctly spelled etc.
Result of console.log:
deserializing user: { _id: 5547e77928d405cc236d4a01,
updated_at: 'Mon May 04 2015 17:41:13 GMT-0400 (EDT)',
created_at: 'Mon May 04 2015 17:41:13 GMT-0400 (EDT)',
admin: false,
lastName: '######',
firstName: '######',
email: '######',
password: '######',
callsign: '######',
uid: '$2a$10$/yF1pqR9N5VkXcnLaNDPBea8xH.tO3Tto82W.9wGD3VdZGPAdXID6',
profilePublic: true,
logPublic: true,
__v: 0 }
Also tried:
-if(user.logPublic)
p It's true
Still nothing

Rails Mongoid search parents elements that have at least one child

I have a rails 4 app and I have 2 objects: stores and books (referenced 1:n relation).
A store has many books, each book belongs to one store. Some stores don't have any books.
How can I make a query to find the 3 latest store that has at least 1 book - and the 3 latest stores that have no books ?
#stores = Store.order_by(:created_at => 'desc').limit(4).uniq
#books = Book.order_by(:created_at => 'desc').limit(4).uniq
This work but I don't know how to do a where(book.exists?) for store, or for the #books to make sure each book belongs to a unique store.
Basic CRUD operations in MongoDB operate on a single collection,
"join" capability is not yet implemented that would allow them to operate across two collections.
Once you understand this, you can easily construct two operations that will do what you want.
The following is the most obvious given the schema hints that you supplied.
To do anything more, you probably want to consider schema changes like embedding.
By definition, your supplied schema only allows a book to belong to one (unique by definition) store.
You can see this from the inspection of the books, that there is a single value store_id for each book.
Hope that this helps your understanding.
app/models/store.rb
class Store
include Mongoid::Document
include Mongoid::Timestamps
field :name, type: String
has_many :books
end
app/models/book.rb
class Book
include Mongoid::Document
include Mongoid::Timestamps
field :title, type: String
belongs_to :store
end
test/unit/store_test.rb
require 'test_helper'
require 'pp'
class StoreTest < ActiveSupport::TestCase
def setup
Mongoid.default_session.drop
end
test '0. mongoid version' do
puts "\nMongoid::VERSION:#{Mongoid::VERSION}\nMoped::VERSION:#{Moped::VERSION}"
end
test 'store query has book, does not have book' do
[
["Amazon.com", ["Outlander", "Taking It All"]],
["Barnes & Noble", ["Big Little Lies"]],
["Goodreads", []],
["Greenlight Bookstore", []],
["Powell's Books", ["Gone Girl", "Dark Skye"]],
["Strand Books", []]
].each do |store, books|
store = Store.create(name: store)
books.each do |title|
store.books << Book.create(title: title)
end
sleep 1
end
assert_equal(6, Store.count)
assert_equal(5, Book.count)
puts
store_ids_with_books = Book.distinct(:store_id)
latest_stores_with_a_book = Store.in(_id: store_ids_with_books).order_by(:created_at => 'desc').limit(3).to_a
puts "three latest stores with a book:"
pp latest_stores_with_a_book
latest_stores_without_a_book = Store.nin(_id: store_ids_with_books).order_by(:created_at => 'desc').limit(3).to_a
puts "three latest stores without a book:"
pp latest_stores_without_a_book
puts "books:"
pp Book.all.to_a
end
end
rake test
Run options:
# Running tests:
[1/2] StoreTest#test_0._mongoid_version
Mongoid::VERSION:3.1.6
Moped::VERSION:1.5.2
[2/2] StoreTest#test_store_query_has_book,_does_not_have_book
three latest stores with a book:
[#<Store _id: 53f257287f11ba75e5000008, created_at: 2014-08-18 19:42:32 UTC, updated_at: 2014-08-18 19:42:32 UTC, name: "Powell's Books">,
#<Store _id: 53f257257f11ba75e5000004, created_at: 2014-08-18 19:42:29 UTC, updated_at: 2014-08-18 19:42:29 UTC, name: "Barnes & Noble">,
#<Store _id: 53f257247f11ba75e5000001, created_at: 2014-08-18 19:42:27 UTC, updated_at: 2014-08-18 19:42:27 UTC, name: "Amazon.com">]
three latest stores without a book:
[#<Store _id: 53f257297f11ba75e500000b, created_at: 2014-08-18 19:42:33 UTC, updated_at: 2014-08-18 19:42:33 UTC, name: "Strand Books">,
#<Store _id: 53f257277f11ba75e5000007, created_at: 2014-08-18 19:42:31 UTC, updated_at: 2014-08-18 19:42:31 UTC, name: "Greenlight Bookstore">,
#<Store _id: 53f257267f11ba75e5000006, created_at: 2014-08-18 19:42:30 UTC, updated_at: 2014-08-18 19:42:30 UTC, name: "Goodreads">]
books:
[#<Book _id: 53f257247f11ba75e5000002, created_at: 2014-08-18 19:42:28 UTC, updated_at: 2014-08-18 19:42:28 UTC, title: "Outlander", store_id: "53f257247f11ba75e5000001">,
#<Book _id: 53f257247f11ba75e5000003, created_at: 2014-08-18 19:42:28 UTC, updated_at: 2014-08-18 19:42:28 UTC, title: "Taking It All", store_id: "53f257247f11ba75e5000001">,
#<Book _id: 53f257257f11ba75e5000005, created_at: 2014-08-18 19:42:29 UTC, updated_at: 2014-08-18 19:42:29 UTC, title: "Big Little Lies", store_id: "53f257257f11ba75e5000004">,
#<Book _id: 53f257287f11ba75e5000009, created_at: 2014-08-18 19:42:32 UTC, updated_at: 2014-08-18 19:42:32 UTC, title: "Gone Girl", store_id: "53f257287f11ba75e5000008">,
#<Book _id: 53f257287f11ba75e500000a, created_at: 2014-08-18 19:42:32 UTC, updated_at: 2014-08-18 19:42:32 UTC, title: "Dark Skye", store_id: "53f257287f11ba75e5000008">]
Finished tests in 6.193234s, 0.3229 tests/s, 0.3229 assertions/s.
2 tests, 2 assertions, 0 failures, 0 errors, 0 skips

Resources