Reputation: 5804
I'm trying to create a mixins for authentication login, so it can be applied to my models which should be able to login. Much like the the has_secure_password in Ruby.
Afaik this is done using the use
statement which essential requires the module, and calls the __using__
macro. So I implemented my mixin like this.
defmodule MyApp.SecurePassword do
defmacro __using__(_options) do
quote do
import MyApp.SecurePassword
end
end
defmacro authenticate(password) do
# Lets return true, for testing purposes.
true
end
end
I'm then calling the use, in my "user" model.
defmodule MyApp.Farm do
use MyApp.Web, :model
use MyApp.SecurePassword
schema "farms" do
field :name, :string
field :email, :string
#.....
In my controller, i'm then trying to use the method.
def create(conn, %{"session" => session_params}) do
user = Repo.get_by(Farm, email: session_params["email"])
if user && user.authenticate(session_params["password"]) do
conn = put_flash(conn, :success, "You were successfully logged in")
else
conn = put_flash(conn, :error, "Credentials didn't match")
end
redirect(conn, to: session_path(conn, :new))
end
But when i hit the code, i just get a argument error, on the line where i call the authenticate function.
My macro skills is rather weak, what am i doing wrong? :)
Upvotes: 4
Views: 659
Reputation: 23164
I think what you want is to call the authenticate
function passing in the user and the password:
def authenticate(user, password) do
# auth logic
end
And then:
import MyApp.SecurePassword
# ...
if user && authenticate(user, session_params["password"]) do
# ...
For now there doesn't seem to be any reason to use a macro or a use
, a simple import
will do - you only want those when generating some code compile-time and in this case it seems everything you want will be happening at runtime.
Upvotes: 6