标签: elixir

Elixir混合自动确认

我想在Travis-CI上运行我的Phoenix应用程序的测试.

日志摘录:

$ MIX_ENV=test mix do deps.get, compile, test

Could not find hex, which is needed to build dependency :phoenix

Shall I install hex? [Yn] 
Run Code Online (Sandbox Code Playgroud)

在获取和安装依赖项时,它会询问是否应该安装hex.我想知道我是否可以通过--yes混合选项,以便它不会问但只是安装?

hex elixir-mix elixir travis-ci

10
推荐指数
2
解决办法
4431
查看次数

如何获得elixir中每种类型的最小值和最大值

如何获得灵丹妙药中每种类型的最小值和最大值?例如,一个整数,浮点数和一个字符串的最大可能长度.

我知道在C中它定义为limits.has INT_MIN,INT_MAX依此类推.关于灵丹妙药中这些类型的限制的文件?

elixir

10
推荐指数
1
解决办法
4623
查看次数

如何在Elixir应用程序中找到工作人员?

通过入门教程的主管和应用程序部分,我正在为底部的监督树问题编写单元测试.我尝试启动顶级主管,但失败了,出现此错误:

  1) test all buckets die if registry dies (KV.SupervisorTest)
     test/kv/supervisor_test.exs:4
     ** (EXIT from #PID<0.111.0>) shutdown: failed to start child: GenEvent
         ** (EXIT) already started: #PID<0.75.0>
Run Code Online (Sandbox Code Playgroud)

显然应用程序已经启动,因此我需要访问其工作进程.如果我有主管,我可以使用Supervisor.which_children来获取它们.要做到这一点,也许有助于运行kv应用程序:

iex(28)> kvpid = :application.info[:running][:kv]
#PID<0.77.0>
Run Code Online (Sandbox Code Playgroud)

所以现在我有了应用程序的PID.是否有某种方法可以从中获取根管理程序进程,或者我是否必须手动将其注册到某处以从测试中获取它?

或者有没有办法直接从他们的名字中获取工人?我试过:erlang.whereis但它找不到工人:

iex(33)> :erlang.whereis KV.Registry
:undefined
Run Code Online (Sandbox Code Playgroud)

我尝试直接使用模块的名称,但这也不起作用:

test "all buckets die if registry dies" do
    reg = KV.Registry
    KV.Registry.create(reg, "shopping")
    {:ok, shopping_bucket} = KV.Registry.lookup(reg, "shopping")

    Process.exit(reg, :shutdown)
    assert_receive {:exit, "shopping", ^shopping_bucket}
end
Run Code Online (Sandbox Code Playgroud)

它失败并出现此错误:

1) test all buckets die if registry dies (KV.SupervisorTest) …
Run Code Online (Sandbox Code Playgroud)

elixir erlang-otp

10
推荐指数
2
解决办法
4272
查看次数

哈克尼未能向服务器提出请求

我正在使用Phoenix Framework运行以下内容以连接到https://api.twitch.tv/kraken/videos/top.它过去曾奏效,并不确定导致此案发生的原因.停止并重新启动iex似乎没有解决它.运行Elixir 1.0.5,Phoenix 0.14.0,Erlang OTP 18

iex(2)> "https://api.twitch.tv/kraken/videos/top" |> 
...(2)> HTTPoison.get!()
** (exit) exited in: :gen_server.call(:hackney_manager, {:new_request, #PID<0.334.0>, #Reference<0.0.2.365>, {:client, :undefined, :hackney_dummy_metrics, :hackney_ssl_transport, 'api.twitch.tv', 443, "api.twitch.tv", [connect_timeout: 5000, recv_timeout: :infinity], nil, nil, nil, true, :hackney_pool, :infinity, false, 5, false, 0, nil, nil, nil, :undefined, :start, nil, :normal, false, false, false, nil, :waiting, nil, 4096, "", [], :undefined, nil, nil, nil, nil, :undefined, nil}}, :infinity)
    ** (EXIT) no process
    (stdlib) gen_server.erl:212: :gen_server.call/3
             src/hackney_client/hackney_manager.erl:65: :hackney_manager.init_request/1
             src/hackney_client/hackney_manager.erl:55: :hackney_manager.new_request/1
             src/hackney_connect/hackney_connect.erl:181: :hackney_connect.socket_from_pool/4
             src/hackney_connect/hackney_connect.erl:41: …
Run Code Online (Sandbox Code Playgroud)

elixir phoenix-framework

10
推荐指数
1
解决办法
1715
查看次数

Phoenix App中预编译的单页应用程序

我有一个预编译的ember.js应用程序(fronted-js-framework在这里不重要),它基本上由一个带有index.html文件的文件夹和一些js/css资产组成.

我把这个文件夹放在我的凤凰应用程序中的/ priv/static下,并试图让路由服务它...到目前为止没有成功.我在凤凰版0.17.1(与1.0 afaik相同).我按顺序尝试了以下步骤:

  • 在endpoint.ex中,我删除了only: ~w(...)过滤器.
  • 通过单个操作实现了一个最小的控制器来提供文件: def index(conn, _params) do redirect conn, to: "/my_app/index.html" end
  • 将控制器添加到我的routes.ex: get "/my_app", MyCustomController, :index

到目前为止,上述步骤均无效,我只得到错误no route found for GET /my_app/index.html.我怎么能解决这个问题?我只想将URL "/my_app"(或者,如果没有其他工作原理"/my_app/index.html")映射到priv/static/my_app/index.html我的凤凰应用程序中的路径.有任何想法吗?

编辑:

我尝试实现的基本工作流程如下:

我有不同的开发人员在其专用文件夹中构建一些ember.js SPA $phoenix_root/apps/.所以我有一个$phoenix_root/apps/my_app带有ember和ember-cli 的开发人员.这个开发人员ember server在开发他的应用程序时使用,并且mix phoenix.server在后台运行,因为phoenix应用程序本身将所需数据公开为RESTful API.

在每个实现的功能,前端开发人员类型之后ember build [...],此任务将整个ember.js前端应用程序编译到一个文件夹中,带有index.html文件和一些资源,并将此文件夹移动到$phoenix_root/web/static/assets/my_app.然后凤凰(或早午餐)触发,并复制这个东西原样$phoenix_root/priv/static/my_app,随时可以提供像任何其他资产.

关键是能够在单个代码库(凤凰应用程序)中构建一堆孤立的"前端"作为自包含的包,而凤凰应用程序本身还有其他(其他)要做的事情.

因为Frontend-Developers每次都自动生成SPA,所以我非常想避免修改新的index.html文件.在性能方面,将这些SPA作为静态文件提供服务是最好的 - 它们在用户浏览器内自行初始化.

我希望这可以为我这样做添加一些说明.

编辑2:

我现在有一个工作解决方案,请参阅我为演示目的创建的示例repo:https://github.com/Anonyfox/Phoenix-Example-Multiple-SPA-Frontends

凤凰应用程序的必要修改:

  • 修改endpoint.ex …

elixir single-page-application phoenix-framework

10
推荐指数
1
解决办法
2309
查看次数

如何使用Phoenix向特定套接字发送消息

我有一些验证套接字:

defmodule Test.UserSocket do
  use Phoenix.Socket

  ## Channels
  channel "user:*", Test.RoomChannel

  def connect(_params, socket) do
    case Phoenix.Token.verify(socket, "user",  _params["token"]) do
          {:ok, uid} ->
            {:ok, assign(socket, :user_id, uid)}
          {:error, _} ->
            :error
     end
  end

 def id(_socket), do: "user:#{_socket.assigns.user_id}"
end
Run Code Online (Sandbox Code Playgroud)

并在连接套接字后命名为 user:#id

从文档中我可以发送断开连接事件 Test.Endpoint.broadcast("users_socket:" <> user.id, "disconnect", %{})

问题:如何将自定义事件发送到套接字user:#id,它应该像是对特定套接字的推送通知.

我试过Test.Endpoint.broadcast "user:1", "new:msg", %{user: "SYSTEM", body: "iex"}但它不起作用,因为我无法在套接字上听"new:msg".

elixir phoenix-framework

10
推荐指数
1
解决办法
3074
查看次数

构建GenServer调用self的正确方法

我知道让GenServer进程调用本身几乎是不可能的,因为你基本上遇到了死锁.但是,我很好奇是否有一种首选方式来做这种事情.

假设以下场景:我有一个队列,我正在弹出的东西.如果队列是空的,我想重新填充它.我可以像这样构造它:

def handle_call(:refill_queue, state) do
  new_state = put_some_stuff_in_queue(state)
  {:reply, new_state}
end

def handle_call(:pop, state) do
  if is_empty_queue(state) do
    GenServer.call(self, :refill_queue)
  end

  val,new_state = pop_something(state)

  {:reply, val, new_state}
end
Run Code Online (Sandbox Code Playgroud)

这里的一个大问题是,当我们尝试重新填充队列时,这将会死锁.我过去使用的一个解决方案是使用cast更多,因此它不会死锁.像这样(的变化callcast进行补充)

def handle_cast(:refill_queue, state) do
Run Code Online (Sandbox Code Playgroud)

但在这种情况下,我认为它不起作用,因为pop在实际填充队列之前,异步转换重新填充队列可能会返回,这意味着我将尝试弹出一个空队列.

无论如何,核心问题是:处理这个问题的最佳方法什么?我假设答案是put_some_stuff_in_queue直接在pop通话中打电话,但我想检查一下.换句话说,它似乎是做正确的事是使handle_callhandle_cast尽可能简单,基本上只是包装来在实际工作情况等功能.然后,创建尽可能多的handle_*函数来覆盖您将要处理的所有可能情况,而不是handle_call(:foo)依次调用handle_call(:bar).

elixir gen-server

10
推荐指数
1
解决办法
2272
查看次数

在Elixir中创建闭包

我有一个Sequence结构,由一个state和一个generator函数组成,该函数从旧的生成新状态.我想写一个limit返回一个新的序列应当完全返回新的状态函数n的最大值和每一个时代n + k它应该返回时间nil.到目前为止的代码是:

defmodule Sequence do
  defstruct [:state, :generator]

  def generate(%Sequence{state: nil}) do
    nil
  end

  def generate(%Sequence{state: state , generator: generator } = seq) do
    {old_state, new_state} = generator.(state) 
    { old_state,  %Sequence{ seq | state: new_state } }
  end

  def limit(%Sequence{ generator: generator } = seq, n) when n > -1 do
    lim_gen = create_limit_gen(generator, n)
    %Sequence{ seq | generator: lim_gen }
  end

  defp create_limit_gen(generator, n) …
Run Code Online (Sandbox Code Playgroud)

closures elixir

10
推荐指数
1
解决办法
938
查看次数

Phoenix Framework的Plug.Conn中assign和put_session有什么区别?

文档(https://hexdocs.pm/plug/Plug.Conn.html)命名两个函数,允许在一个键值对中存储conn

assign(conn, key, value)
Run Code Online (Sandbox Code Playgroud)

为连接中的键分配值

put_session(conn, key, value)
Run Code Online (Sandbox Code Playgroud)

将指定值放在给定键的会话中

这两个功能有什么区别?

session elixir phoenix-framework

10
推荐指数
1
解决办法
1454
查看次数

即使似乎授予访问权限,Google Calendar API在OAuth期间也会出现403错误

我的应用会在用户的Google日历上发布,修改和删除活动.我正在配置OAuth以实现这一目标.这个想法是,在注册后,用户将能够进入他们的设置并同意将我的应用程序连接到他们的Google日历.然后,我将能够在数据库中存储oauth令牌和刷新令牌,并在用户日历上创建/编辑/删除事件时使用它们.

无论如何,问题是我选择了我的帐户:

选择帐户

然后我点击"允许"提供同意:

允许访问

以下是它变得奇怪的地方:在幕后,Google Calendar API会报告403 Forbidden错误.

%Ueberauth.Failure{errors: [%Ueberauth.Failure.Error{message: 403,
message_key: "OAuth2"}], provider: :google,
strategy: Ueberauth.Strategy.Google}
Run Code Online (Sandbox Code Playgroud)

我的ueberauth配置:

config :ueberauth, Ueberauth,
  providers: [
    google: {Ueberauth.Strategy.Google, [default_scope: "https://www.googleapis.com/auth/calendar", approval_prompt: "force", access_type: "offline"]}
]
Run Code Online (Sandbox Code Playgroud)

我正在提出的要求:

def callback(%{assigns: %{ueberauth_failure: fail}} = conn, _params) do
  IO.inspect fail
  conn
  |> put_flash(:error, "Failed to authenticate.")
  |> redirect(to: "/")
end

def callback(%{assigns: %{ueberauth_auth: auth}} = conn, _params) do
  IO.inspect auth
  conn
  |> put_flash(:success, "Connected to Google.")
  |> redirect(to: "/")
end
Run Code Online (Sandbox Code Playgroud)

第一个callback函数是匹配的函数(因为它失败).

但是,当我转到我的Google帐户时,我可以看到该应用已被授予权限:

授予访问权限

我提供了正确的client_id和client_secret.此外,我在Google …

google-calendar-api elixir oauth-2.0 google-oauth

10
推荐指数
1
解决办法
523
查看次数