Ecto: How to Inject data on changeset, without Model.Callbacks - postgresql

Ecto.Model.Callbacks are now deprecated.
I am trying to achieve the same behavior as before_insert but to no avail! I can't even get anything to trigger IO.puts("hello") inside my changeset/2.
Here's what I have:
def changeset(model, params \\ :empty) do
IO.puts "HELLO" # never prints
model
|> cast(params, #required_fields, #optional_fields)
|> put_change(:column_name, "hello")
end
Instead of put_change, I've tried subbing change, cast, and practically everything else inside Ecto.Changeset.
I've also tried the non-piping method, just in case:
chset = cast(model, params, #required_fields, #optional_fields)
put_change(chset, :column_name, "hello")
The end-goal is shifting the row's inserted_at for a new value, so a simple default: "hello" on the Schema won't suffice.
Many thanks!

I ended up solving it via a Postgres fragment.
It's not quite what I was looking for, so I'll leave this question open for someone with an answer involving the changset, because that's still doing absolutely nothing for me.
Here's my temporary solution, involving the postgres Migration file.
create table(:stuffs) do
add :expires_at, :datetime, default: fragment("now() + interval '60 days'")
end

Related

Get update db (in postgres) notifications in phoenix

I need to now when a row changed in my db. I'm using phoenix 1.2.4. I already have the triggers using postgres, but actually I don't know if I need them.
Do you know how could I solve my problem?
NOTE: The data base isn't necessarily changed from the controllers, rather I have a cron that update some parts.
I saw this tutorial (Publish/subscribe with PostgreSQL and Phoenix Framework) a few days ago and it seems like it contains exactly what you want.
It sets up the notification from the DB and then broadcast it. In your case, you just need the notification part and should be all good.
I hope that helps :)
Postgrex.Notifications is the module which will use postgresql listen/notify to deliver messages to an elixir process.
A simple example:
defmodule MyListener do
use GenServer
def start_link(), do: GenServer.start_link(__MODULE__, [])
def init(_arg) do
{:ok, pid} = Postgrex.Notifications.start_link(MyRepo.config())
Postgrex.Notifications.listen(pid, "my_table")
{:ok, []}
end
def handle_info({:notification, _connection_pid, _ref, _channel, payload}, state) do
# ... do something with payload ...
{:noreply, state}
end
end

Elixir's comeonin does not seem to be checking hashes correctly

So I recently decided I wanted to learn Elixir for the new year, and have been going through the Phoenix framework's book on how web development works in Elixir.
So far I am really enjoying it, and am already starting to love the language. I've come across a few issues with the Come-on-in package though.
One was compiling it, which is fine. But I am wondering if it is causing problems, the issue is I am having trouble figuring out how to debug this issue.
defmodule Rumbl.Auth do
import Plug.Conn
def init(opts) do
Keyword.fetch!(opts, :repo)
end
def call(conn, repo) do
user_id = get_session(conn, :user_id)
user = user_id && repo.get(Rumbl.User, user_id)
assign(conn, :current_user, user)
end
def login(conn, user) do
conn
|> assign(:current_user, user)
|> put_session(:user_id, user.id)
|> configure_session(renew: true)
end
def logout(conn) do
configure_session(conn, drop: true)
end
import Comeonin.Bcrypt, only: [checkpw: 2, dummy_checkpw: 0]
def login_by_username_and_pass(conn, username, given_pass, opts) do
repo = Keyword.fetch!(opts, :repo)
user = repo.get_by(Rumbl.User, username: username)
cond do
user && checkpw(given_pass, user.password_hash) ->
{:ok, login(conn, user)}
user ->
{:error, :unauthorized, conn}
true ->
dummy_checkpw()
{:error, :not_found, conn}
end
end
end
That is the code, and everything is compiling and I can see it's being sent through correctly. But for some reason the password is never being resolved. I made another user with the password "password" and even did something like this:
checkpw("password", "$2b$12$aa4dos3r4YwX7HKgj.JiL.bEzg42QjxBvWwm5M")
Just to see if it was how I was passing the information, obviously that is the hash in my database, and that also does not work. I am at a loss to what I am doing wrong, or since this is my first time using Bcrypt and am not 100% sure how the salting works if it's how I am using the library itself.
I am hashing the passwords with this:
defp put_pass_hash(changeset) do
case changeset do
%Ecto.Changeset{valid?: true, changes: %{password: pass}} ->
put_change(changeset, :password_hash, Comeonin.Bcrypt.hashpwsalt(pass))
_ ->
changeset
end
end
I've looked over everything I can think of, and it all looks correct, but for some reason Comeonin is not comparing the passwords correctly. Any help would be much appreciated, thanks!
The issue I was having was not anything to do with Elixir or the Comeonin library!
I had only allowed a Varchar of 45 for my passwords, and it was truncating the response. I am just going to leave this here in case anyone does something as silly as this in the future!

How to suppress printing of variable values in zeppelin

Given the following snippet:
val data = sc.parallelize(0 until 10000)
val local = data.collect
println(s"local.size")
Zeppelin prints out the entire value of local to the notebook screen. How may that behavior be changed?
You can also try adding curly brackets around your code.
{val data = sc.parallelize(0 until 10000)
val local = data.collect
println(s"local.size")}
Since 0.6.0, Zeppelin provides a boolean flag zeppelin.spark.printREPLOutput in spark's interpreter configuration (accessible via the GUI), which is set to true by default.
If you set its value to false then you get the desired behaviour that only explicit print statements are output.
See also: https://issues.apache.org/jira/browse/ZEPPELIN-688
What I do to avoid this is define a top-level function, and then call it:
def run() : Unit = {
val data = sc.parallelize(0 until 10000)
val local = data.collect
println(local.size)
}
run();
FWIW, this appears to be new behaviour.
Until recently we have been using Livy 0.4, it only output the content of the final statement (rather than echoing the output of the whole script).
When we upgraded to Livy 0.5, the behaviour changed to output the entire script.
While splitting the paragraph and hiding the output does work, it seems like an unnecessary overhead to the usability of Zeppelin.
for example, if you need to refresh your output, then you have to remember to run two paragraphs (i.e. the one that sets up your output and the one containing the actual println).
There are, IMHO, other usability issues with this approach that makes, again IMHO, Zeppelin less intuitive to use.
Someone has logged this JIRA ticket to address "the problem", please vote for it:
LIVY-507
Zeppelin, as well as spark-shell REPL, always prints the whole interpreter output.
If you really want to have only local.size string printed - best way to do it is to put println "local.size" statement inside the separate paragraph.
Then you can hide all output of the previous paragraph using small "book" icon on the top-right.
a simple trick I am using is to define
def !() ="_ __ ___ ___________________________________________________"
and use as
$bang
above or close to the code I want to check
and it works
res544: String = _ __ ___ ___________________________________________________
then I just leave there commented out ;)
// hope it helps

Erlang mnesia equivalent of "select * from Tb"

I'm a total erlang noob and I just want to see what's in a particular table I have. I want to just "select *" from a particular table to start with. The examples I'm seeing, such as the official documentation, all have column restrictions which I don't really want. I don't really know how to form the MatchHead or Guard to match anything (aka "*").
A very simple primer on how to just get everything out of a table would be very appreciated!
For example, you can use qlc:
F = fun() ->
Q = qlc:q([R || R <- mnesia:table(foo)]),
qlc:e(Q)
end,
mnesia:transaction(F).
The simplest way to do it is probably mnesia:dirty_match_object:
mnesia:dirty_match_object(foo, #foo{_ = '_'}).
That is, match everything in the table foo that is a foo record, regardless of the values of the fields (every field is '_', i.e. wildcard). Note that since it uses record construction syntax, it will only work in a module where you have included the record definition, or in the shell after evaluating rr(my_module) to make the record definition available.
(I expected mnesia:dirty_match_object(foo, '_') to work, but that fails with a bad_type error.)
To do it with select, call it like this:
mnesia:dirty_select(foo, [{'_', [], ['$_']}]).
Here, MatchHead is _, i.e. match anything. The guards are [], an empty list, i.e. no extra limitations. The result spec is ['$_'], i.e. return the entire record. For more information about match specs, see the match specifications chapter of the ERTS user guide.
If an expression is too deep and gets printed with ... in the shell, you can ask the shell to print the entire thing by evaluating rp(EXPRESSION). EXPRESSION can either be the function call once again, or v(-1) for the value returned by the previous expression, or v(42) for the value returned by the expression preceded by the shell prompt 42>.

squeryl date to long conversion - query hangs on simple operation

kind of a follow up question to my previous one:
squeryl date to long conversion
I implemented a DateTime(model) to Long(DB) conversion as mentioned in that thread.
I wrote a simple query to delete all records with an expired date:
println("deleting expired")
val now: DateTime = new DateTime()
inTransaction {
MyDB.loginTokens.deleteWhere(t =>
t.expires lt now.getMillis
)
}
println("finished deleting")
but the query just hangs in there and does nothing, no error is thrown...
I only see "deleting expired" printed and never "finished".
I also tried "t.expires lt now" and some other variants without success.
any idea what's causing this and how to fix it?
EDIT
when changing lt to .~ <, there is still a problem
when changing lt to === the query works fine both with now and now.getMillis.
t.expires.~ lt now
Notice the dot tilda.
Not sure why "lt" by itself doesn't work, like === works.
perhaps its a synonym to something else...