点击次数后重定向

时间:2016-12-01 18:01:11

标签: ruby logic elixir

我有很多网址。我需要与一些人分享这些网址。 我需要将这些网址转换为新的网址,以便:=>点击每个网址5次后,他们应该重定向到登录页面。

e.g。 www.abc.com/m => www.abc.com/m1234(我们分享的这个)=>点击5次后=>登录页面。

注意:www.abc.com/m需要登录。 www.abc.com/m1234不需要登录5次尝试,它会打开www.abc.com/m

我需要用elixir / ruby​​来解决这个问题。 如果不包括DB,有什么方法可以做到吗?

这样做的最佳方法是什么?

1 个答案:

答案 0 :(得分:1)

在标记elixir和ruby时,不完全确定您的堆栈是什么,但一种解决方案是使用Agent模块。另一种解决方案是使用ETS/DETS Table

这实际上是一个基于状态的GenServer包装器,对于类似的东西来说是完美的。

基本上,根据您的堆栈,您会向正在运行代理的elixir / phoenix应用程序发送消息。

例如:

#lib/appname.ex

  def start(_type, _args) do
    import Supervisor.Spec, warn: false

    children = [
      worker(AppName.ClickCounter.start_link, [])
    ]

    opts = [strategy: :one_for_one, name: Test.Supervisor]
    Supervisor.start_link(children, opts)
  end

以上在应用程序启动后启动代理,如果发生故障或崩溃,将重新启动代理。

然后在你的MyApp.ClickCounter模块中:

defmodule MyApp.ClickCounter do

  @doc """
  Starts the Agent and registers it's process id under the name of the module name. Initializes it's state as an empty map.
  """
  def start_link do
    Agent.start_link(fn -> %{} end, name: __MODULE__)
  end

  @doc """
  Takes in a string url and increments it's click count by one.

  If there is no counter for the url already it will create one with a default value of 0.
  """
  def increment_counter(url), do: update_state(url)

  @doc """
  Returns the current value of the counter for the given url
  """
  def get_counter(url), do: Agent.get(__MODULE__, &(Map.fetch!(&1, url)))

  defp update_state(value) do
    Agent.update(__MODULE__, fn(state) -> 
     Map.update(state, value, 1, fn(count) -> 
      count + 1
     end)
    end)
  end
end

然后启动iex -S mix控制台并播放它。

iex(1)> MyApp.ClickCounter.increment_counter("http://google.com/123")
:ok
iex(2)> MyApp.ClickCounter.get_counter("http://google.com/123")
1
iex(3)> MyApp.ClickCounter.increment_counter("http://google.com/123")
:ok
iex(4)> MyApp.ClickCounter.increment_counter("http://google.com/123")
:ok
iex(5)> MyApp.ClickCounter.increment_counter("http://google.com/123")
:ok
iex(6)> MyApp.ClickCounter.get_counter("http://google.com/123")
4

从上面可以看出,您可以将任何想要的逻辑应用于更新,检索方法。由于它存储在一个过程中,因此速度非常快。

如果需要保持这种状态,你可以使用类似ETS / DETS的东西,它可以将表保存到磁盘,并在重启/崩溃时加载现有数据。

另一种持久化的方法可能是拥有一个数据库,然后拥有一个流程工作者(简单的方法是使用GenServer并让它实现Process.send_after(x,x, 1000ms)类的东西),它通过状态和再次将其保留在数据库中,以便您从崩溃中恢复。