Elixir, phoenix, ecto : can't add data to my tables - postgresql

I am trying to add rows to the table 'users' I have created, but I get this error:
iex(3)> user = %User{username: "mel", email: "mail"}
%Theme01.User{
__meta__: #Ecto.Schema.Metadata<:built, "user">,
id: nil,
email: "mail",
username: "mel",
clocks: #Ecto.Association.NotLoaded<association :clocks is not loaded>,
inserted_at: nil,
updated_at: nil
}
iex(4)> user = Repo.insert(User)
** (FunctionClauseError) no function clause matching in Ecto.Repo.Schema.insert/4
The following arguments were given to Ecto.Repo.Schema.insert/4:
# 1
Theme01.Repo
# 2
Theme01.Repo
# 3
Theme01.User
# 4
{%{
adapter: Ecto.Adapters.Postgres,
cache: #Reference<0.388300084.2616328193.258496>,
opts: [
repo: Theme01.Repo,
timeout: 15000,
pool_size: 10,
pool: DBConnection.ConnectionPool
],
pid: #PID<0.402.0>,
repo: Theme01.Repo,
sql: Ecto.Adapters.Postgres.Connection,
stacktrace: true,
telemetry: {Theme01.Repo, :debug, [:theme01, :repo, :query]}
},
[
stacktrace: [
{Ecto.Repo.Supervisor, :tuplet, 2,
[file: 'lib/ecto/repo/supervisor.ex', line: 162]},
{Theme01.Repo, :insert, 2, [file: 'lib/theme01/repo.ex', line: 2]},
{:elixir, :"-eval_external_handler/1-fun-2-", 4,
[file: 'src/elixir.erl', line: 298]},
{:erl_eval, :do_apply, 7, [file: 'erl_eval.erl', line: 748]},
{:erl_eval, :expr, 6, [file: 'erl_eval.erl', line: 492]},
{:elixir, :eval_forms, 3, [file: 'src/elixir.erl', line: 288]},
{Module.ParallelChecker, :verify, 1,
[file: 'lib/module/parallel_checker.ex', line: 107]},
{IEx.Evaluator, :eval_and_inspect, 3,
[file: 'lib/iex/evaluator.ex', line: 329]},
{IEx.Evaluator, :eval_and_inspect_parsed, 3,
[file: 'lib/iex/evaluator.ex', line: 303]},
{IEx.Evaluator, :parse_eval_inspect, 3,
[file: 'lib/iex/evaluator.ex', line: 292]},
{IEx.Evaluator, :loop, 1, [file: 'lib/iex/evaluator.ex', line: 187]},
{IEx.Evaluator, :init, 4, [file: 'lib/iex/evaluator.ex', line: 32]},
{:proc_lib, :init_p_do_apply, 3, [file: 'proc_lib.erl', line: 240]}
]
]}
Attempted function clauses (showing 2 out of 2):
def insert(repo, name, -%Ecto.Changeset{} = changeset-, tuplet)
def insert(repo, name, -%{__struct__: _} = struct-, tuplet)
(ecto 3.9.1) lib/ecto/repo/schema.ex:303: Ecto.Repo.Schema.insert/4
iex:4: (file)
Here is the schema of my table :
defmodule Theme01.User do
use Ecto.Schema
import Ecto.Changeset
alias Theme01.Clock
schema "user" do
field :email, :string
field :username, :string
has_many(:clocks, Clock)
timestamps()
end
#doc false
def changeset(user, attrs) do
user
|> cast(attrs, [:username, :email])
|> validate_required([:username, :email])
end
end
and here is the migration function
defmodule Theme01.Repo.Migrations.CreateUser do
use Ecto.Migration
def change do
create table("users") do
add :username, :string, null: false
add :email, :string, null: false
timestamps()
end
create unique_index(:users, [:username])
end
end
I've been stuck on this for way too long, any help will be greatly appreciated
I've checked that my tables exist, and they do appear when I run \dt in psql. I've also checked that my config/dev.exs is set for the correct database.

Repo.insert(User) is an attempt to insert an atom User (see titlecase) into the table.
Instead, you are to create an Ecto.Changeset and then insert it into the database, somewhat like below.
%User{}
|> User.changeset(attrs)
|> Repo.insert()

Related

no process: the process is not alive, for connecting to mongo

Im using mongox fork on my elixir server
it used to work well, untill today, when I keep getting the below error:
GenServer #PID<0.23055.0> terminating
** (stop) exited in: GenServer.call(Mongo.PBKDF2Cache, {\"a9f40827e764c2e9d74318e934596194\", <<88, 76, 231, 25, 765, 153, 136, 68, 54, 109, 131, 126, 543, 654, 201, 250>>, 10000}, 5000)
** (EXIT) no process: the process is not alive or there's no process currently associated with the given name, possibly because its application isn't started
(elixir) lib/gen_server.ex:766: GenServer.call/3
(mongox) lib/mongo/connection/auth/scram.ex:66: Mongo.Connection.Auth.SCRAM.second_message/5
(mongox) lib/mongo/connection/auth/scram.ex:25: Mongo.Connection.Auth.SCRAM.conversation_first/6
(mongox) lib/mongo/connection/auth.ex:29: anonymous fn/3 in Mongo.Connection.Auth.run/1
(elixir) lib/enum.ex:2914: Enum.find_value_list/3
(mongox) lib/mongo/connection/auth.ex:28: Mongo.Connection.Auth.run/1
(mongox) lib/mongo/connection.ex:206: Mongo.Connection.connect/2
(connection) lib/connection.ex:622: Connection.enter_connect/5
Last message: nil
State: %{auth: [{\"my-user\", \"mypassword\"}], database: \"my-db\", opts: [backoff: 1000, hosts: [{\"xxxxxx.mlab.com\", \"17060\"}], port: 17060, hostname: 'xxxxxx.mlab.com', name: MongoPool, max_overflow: 500], queue: %{}, request_id: 0, socket: nil, tail: nil, timeout: 5000, wire_version: nil, write_concern: [w: 1]}
after digging into the code, I figured out:
failed on this row (on the deps):
https://github.com/work-capital/mongox/blob/feature/nan_type_support/lib/mongo/connection/auth/scram.ex#L66
when trying to call to pbkdf2
which makes a genserver call
def pbkdf2(password, salt, iterations) do
GenServer.call(#name, {password, salt, iterations})
is this an error with the connecting to the mongo instance ( which is on mlab) or is it an issue with the code?
here are my configs:
config.exs
config :mongo_app, MongoApp,
host: "xxxx.mlab.com",
database: "my-db",
username: "my-user",
password: "mypass**",
port: "17060",
pool_size: "100",
max_overflow: "500"
mix.exs:
def application do
[extra_applications: [:logger, :poolboy],
mod: {MongoApp.Application, []}]
end
defp deps do
[{:mongox, git: "https://github.com/work-capital/mongox.git", branch: "feature/nan_type_support"},
{:poolboy, "~> 1.5"}
]
application.ex:
defmodule MongoApp.Application do
use Application
def start(_type, _args) do
MongoApp.connect
import Supervisor.Spec, warn: false
children = [
]
opts = [strategy: :one_for_one, name: MongoApp.Supervisor]
Supervisor.start_link(children, opts)
end
end

How to run the getRole command using pymongo?

I want to check whether a role exists in a mongodb, before I create a new one . I tried to do it the following way:
result = self.client[database].command("getRole", name=app_name)
Unfortunately I get the following error:
msg = msg or "%s"
raise OperationFailure(msg % errmsg, code, response)
pymongo.errors.OperationFailure: no such command: 'getRole', bad cmd: '{ getRole: 1, name: "test" }'
I am referring to this database command: https://docs.mongodb.com/manual/reference/method/db.getRole/
For createRole I can execute the command: https://docs.mongodb.com/manual/reference/method/db.createRole/#db.createRole
Shell methods db.* are different from Database commands.
Using the roleInfo command you can get information for a particular role.
db.command({
'rolesInfo': {'role': 'noremove','db': 'test'},
'showPrivileges': True, 'showBuiltinRoles': True
})
The above command returns a result in this form when there is a matching role:
{'ok': 1.0,
'roles': [{'db': 'test',
'inheritedPrivileges': [{'actions': ['find', 'insert', 'update'],
'resource': {'collection': 'test', 'db': 'test'}}],
'inheritedRoles': [],
'isBuiltin': False,
'privileges': [{'actions': ['find', 'insert', 'update'],
'resource': {'collection': 'test', 'db': 'test'}}],
'role': 'noremove',
'roles': []}]}
When there is no matching role, you get this result:
{'ok': 1.0, 'roles': []}
Checking that a role exists falls to checking for the length of the "roles" list in the returned result as follow:
noremove_role = db.command({
'rolesInfo': {'role': 'noremove','db': 'test'},
'showPrivileges': True, 'showBuiltinRoles': True
})
if not len(noremove_role['roles']):
# create role
pass
Is there a better way?
Yes, in keeping with ask forgiveness not permission philosophy, create the role and handle the resulting exception from trying to add an existing role.
from pymongo.errors import DuplicateKeyError
import logging
logger = logging.getLogger()
try:
db.command(
'createRole', 'noremove',
privileges=[{
'actions': ['insert', 'update', 'find'],
'resource': {'db': 'test', 'collection': 'test'}
}],
roles=[])
except DuplicateKeyError:
logger.error('Role already exists.')
pass

Elixir ecto: check if postgresql map column has key

To use json/jsonb data type ecto suggets to use fragments.
In my case, I've to use PostgreSQL ? operator to see if the map has such key, this however it will become something like:
where(events, [e], e.type == 1 and not fragment("???", e.qualifiers, "?", "2"))
but of course fragment reads the PostgreSQL ? as a placeholder. How can I check if the map has such key?
You need to escape the middle ? and pass a total of three arguments to fragment:
fragment("? \\? ?", e.qualifiers, "2")
Demo:
iex(1)> MyApp.Repo.insert! %MyApp.Food{name: "Foo", meta: %{price: 1}}
iex(2)> MyApp.Repo.insert! %MyApp.Food{name: "Foo", meta: %{}}
iex(3)> MyApp.Repo.all from(f in MyApp.Food, where: fragment("? \\? ?", f.meta, "price"))
[debug] SELECT f0."id", f0."name", f0."meta", f0."inserted_at", f0."updated_at" FROM "foods" AS f0 WHERE (f0."meta" ? 'price') [] OK query=8.0ms
[%MyApp.Food{__meta__: #Ecto.Schema.Metadata<:loaded>, id: 1,
inserted_at: #Ecto.DateTime<2016-06-19T03:51:40Z>, meta: %{"price" => 1},
name: "Foo", updated_at: #Ecto.DateTime<2016-06-19T03:51:40Z>}]
iex(4)> MyApp.Repo.all from(f in MyApp.Food, where: fragment("? \\? ?", f.meta, "a"))
[debug] SELECT f0."id", f0."name", f0."meta", f0."inserted_at", f0."updated_at" FROM "foods" AS f0 WHERE (f0."meta" ? 'a') [] OK query=0.8ms
[]
I'm not sure if this is documented anywhere, but I found the method from this test.

Create a model that belongs_to another in Rails 5

This is my image model:
class Image < ApplicationRecord
belongs_to :user
mount_uploader :avatar, AvatarUploader
end
I can't even create an image in console without a user? Did this change from Rails 4?
Image.create
(0.1ms) begin transaction
(0.1ms) rollback transaction
=> #<Image id: nil, user_id: nil, title: nil, created_at: nil, updated_at: nil, avatar: nil>
2.2.4 :018 > Image.create(title: "hi")
(0.3ms) begin transaction
(0.1ms) rollback transaction
=> #<Image id: nil, user_id: nil, title: "hi", created_at: nil, updated_at: nil, avatar: nil>
2.2.4 :019 > u = User.create
(0.1ms) begin transaction
SQL (0.2ms) INSERT INTO "users" ("created_at", "updated_at") VALUES (?, ?) [["created_at", 2016-03-17 04:27:09 UTC], ["updated_at", 2016-03-17 04:27:09 UTC]]
(8.6ms) commit transaction
=> #<User id: 6, name: nil, created_at: "2016-03-17 04:27:09", updated_at: "2016-03-17 04:27:09">
2.2.4 :020 > u.images << Image.create
(0.1ms) begin transaction
(0.0ms) rollback transaction
(0.0ms) begin transaction
SQL (0.3ms) INSERT INTO "images" ("user_id", "created_at", "updated_at") VALUES (?, ?, ?) [["user_id", 6], ["created_at", 2016-03-17 04:27:16 UTC], ["updated_at", 2016-03-17 04:27:16 UTC]]
(7.8ms) commit transaction
Image Load (0.2ms) SELECT "images".* FROM "images" WHERE "images"."user_id" = ? [["user_id", 6]]
=> #<ActiveRecord::Associations::CollectionProxy [#<Image id: 3, user_id: 6, title: nil, created_at: "2016-03-17 04:27:16", updated_at: "2016-03-17 04:27:16", avatar: nil>]>
I can't get my factories setup:
FactoryGirl.define do
factory :user do
sequence(:name) { |n| "jeff#{n}" }
after(:build) do |user, eval|
user.images << build(:image)
end
end
factory :image do
avatar File.open(File.join(Rails.root, '/spec/support/images/blueapron.jpg'))
end
end
These are my error messsages:
* image - Validation failed: User must exist (ActiveRecord::RecordInvalid)
from /Users/Jwan/.rvm/gems/ruby-2.2.4/gems/factory_girl-4.5.0/lib/factory_girl/linter.rb:4:in `lint!'
from /Users/Jwan/.rvm/gems/ruby-2.2.4/gems/factory_girl-4.5.0/lib/factory_girl.rb:59:in `lint'
from /Users/Jwan/Dropbox/programming/rails/carrierwave_s3/spec/support/factory_girl.rb:10:in `block (2
Yes it changed in rails 5. If you need previous behavior, add optional: true to the belongs_to declaration.

coffeescript error: 'unexpected .' for console.log

Have no idea why I am getting this error but my code:
angular.module('authAppApp')
.factory 'AuthService', (Session) ->
# Service logic
# ...
# Public API here
{
login: (creds)->
res =
id: 1,
user:
id: 1,
role: "admin"
Session.create(res.id, res.user.id, res.user.role)
return
}
Error:
[stdin]:30:14: error: unexpected .
Session.create(res.id, res.user.id, res.user.role)
^
This also happens with console.log
Why?
It looks like your indentation is off:
res =
id: 1,
user:
id: 1,
role: "admin"
Session.create(res.id, res.user.id, res.user.role)
return
The indentation of Session should match the indentation of res =. Otherwise, the coffeescript compiler will parse it as a property of the object you are setting res to. In particular, it's probably expecting a : and a value after Session.