Now Reading
Single File Elixir Scripts · Fly

Single File Elixir Scripts · Fly

2023-03-08 18:39:08

Man fitting an entire script into his head as he runs.
Picture by Annie Ruygt

This text’s about operating single file Elixir scripts. We even present a Phoenix LiveView Instance! Fly.io is a good place to run your Phoenix purposes. Try find out how to get started!

Elixir has highly effective in-built scripting performance, permitting us to jot down Elixir to a file—say my_script.exs— and execute it immediately by elixir my_script.exs.

The overwhelming majority of manufacturing Elixir tasks can be immediately compiled by way of combine with all accessible optimizations and efficiency enhancements enabled. However let’s discover what we will accomplish after we go on script and throw out compilation!

Mix.install/2

The first command to know is Mix.install/2. If you are familiar with Livebook this can be a evaluate, however this command allows set up of any hex package deal. Let’s leap in:

Combine.set up([ 
  :req, 
  {:jason, "~> 1.0"https://fly.io/phoenix-files/single-file-elixir-scripts/} 
])

Req.get!("https://api.github.com/repos/elixir-lang/elixir"https://fly.io/phoenix-files/single-file-elixir-scripts/).physique["description"https://fly.io/phoenix-files/single-file-elixir-scripts/]
|> dbg()

Right here we set up the newest model of the fantastic req HTTP consumer and model 1 for the peerlessly named JSON library jason. As soon as put in, you possibly can instantly use them. Technically we did not want to put in jason as a result of req included it, however I did for instance.

Application.put_env/4

The second function we will need is Application.put_env/4. This operate permits us to place values into the worldwide Software config at runtime. Right here is the bottom setting configuration we want if we need to configure a Phoenix Endpoint:

Software.put_env(:pattern, SamplePhoenix.Endpoint,
    http: [ip: {127, 0, 0, 1}, port: 5001],
    server: true,
    live_view: [signing_salt: "aaaaaaaa"https://fly.io/phoenix-files/single-file-elixir-scripts/],
    secret_key_base: String.duplicate("a"https://fly.io/phoenix-files/single-file-elixir-scripts/, 64)
)

This is not the solely strategy to configure one thing. We might have included an choice to Combine.set up like so:

Combine.set up([ 
      :bandit,
      :phoenix, 
      {:jason, "~> 1.0"https://fly.io/phoenix-files/single-file-elixir-scripts/} 
    ],
    config: [
        sample: [
            SamplePhoenix.Endpoint: [
                http: [ip: {127, 0, 0, 1}, port: 5001],
                server: true,
                live_view: [signing_salt: "aaaaaaaa"https://fly.io/phoenix-files/single-file-elixir-scripts/],
                secret_key_base: String.duplicate("a"https://fly.io/phoenix-files/single-file-elixir-scripts/, 64)
            ]
        ]
    ]
)

Now What?

With those two functions we have the basic foundation to do anything Elixir can do but in a single, portable file!

We can do…

System Administration

retirement = Path.join([System.user_home!(), "retirement"https://fly.io/phoenix-files/single-file-elixir-scripts/])
File.mkrp!(retirement)

# Get rid of those old .ex files who needs em!
Path.wildcard("**/*.ex"https://fly.io/phoenix-files/single-file-elixir-scripts/)
|> Enum.filter(fn f -> 
      {{year, _, _,}, _} = File.stat!(f).mtime 
      year < 2023
   end)
|> Enum.each(fn compiled_file -> 
    File.mv!(compiled_file, retirement) 
    # we only need .exs files now
end)

Data Processing

Mix.install([ 
  :req, 
  :nimble_csv
])
# Req will parse CSVs for us!
Req.get!("https://api.covidtracking.com/v1/us/daily.csv"https://fly.io/phoenix-files/single-file-elixir-scripts/).body
|> Enum.reduce(0, fn row, count -> 
    death_increase = String.to_integer(Enum.at(row, 19))
    count + death_increase
end)
|> IO.puts()

Report Phoenix LiveView Bugs

Let’s say you’ve discovered a bug in LiveView and want to report it. You can increase the odds of it getting fixed quickly by providing a bare-bones example. You could mix phx.new a project and push it up to GitHub, or you could make a single file example and put it in a gist! In fact, Phoenix core contributor Gary Rennie does this so usually that I affectionately name these recordsdata Garyfiles.

Software.put_env(:pattern, SamplePhoenix.Endpoint,
  http: [ip: {127, 0, 0, 1}, port: 5001],
  server: true,
  live_view: [signing_salt: "aaaaaaaa"https://fly.io/phoenix-files/single-file-elixir-scripts/],
  secret_key_base: String.duplicate("a"https://fly.io/phoenix-files/single-file-elixir-scripts/, 64)
)

Combine.set up([
  {:plug_cowboy, "~> 2.5"https://fly.io/phoenix-files/single-file-elixir-scripts/},
  {:jason, "~> 1.0"https://fly.io/phoenix-files/single-file-elixir-scripts/},
  {:phoenix, "~> 1.7.0-rc.2"https://fly.io/phoenix-files/single-file-elixir-scripts/, override: true},
  {:phoenix_live_view, "~> 0.18.2"https://fly.io/phoenix-files/single-file-elixir-scripts/}
])

defmodule SamplePhoenix.ErrorView do
  def render(template, _), do: Phoenix.Controller.status_message_from_template(template)
finish

defmodule SamplePhoenix.SampleLive do
  use Phoenix.LiveView, structure: {__MODULE__, :dwell}

  def mount(_params, _session, socket) do
    {:oops, assign(socket, :depend, 0)}
  finish

  def render("dwell.html"https://fly.io/phoenix-files/single-file-elixir-scripts/, assigns) do
    ~H""https://fly.io/phoenix-files/single-file-elixir-scripts/"
    <script src="https://fly.io/phoenix-files/single-file-elixir-scripts/https://cdn.jsdelivr.internet/npm/phoenix@1.7.0-rc.2/priv/static/phoenix.min.js"></script>
    <script src="https://fly.io/phoenix-files/single-file-elixir-scripts/https://cdn.jsdelivr.internet/npm/phoenix_live_view@0.18.2/priv/static/phoenix_live_view.min.js"></script>
    <script>
      let liveSocket = new window.LiveView.LiveSocket("https://fly.io/phoenix-files/single-file-elixir-scripts//dwell", window.Phoenix.Socket)
      liveSocket.join()
    </script>
    <type>
      * { font-size: 1.1em; }
    </type>

    """
  finish

  def render(assigns) do
    ~H""https://fly.io/phoenix-files/single-file-elixir-scripts/"

    <button phx-click="https://fly.io/phoenix-files/single-file-elixir-scripts/inc">+</button>
    <button phx-click="https://fly.io/phoenix-files/single-file-elixir-scripts/dec">-</button>
    """
  finish

  def handle_event("inc"https://fly.io/phoenix-files/single-file-elixir-scripts/, _params, socket) do
    {:noreply, assign(socket, :depend, socket.assigns.depend + 1)}
  finish

  def handle_event("dec"https://fly.io/phoenix-files/single-file-elixir-scripts/, _params, socket) do
    {:noreply, assign(socket, :depend, socket.assigns.depend - 1)}
  finish
finish

defmodule Router do
  use Phoenix.Router
  import Phoenix.LiveView.Router

  pipeline :browser do
    plug(:accepts, ["html"https://fly.io/phoenix-files/single-file-elixir-scripts/])
  finish

  scope "https://fly.io/"https://fly.io/phoenix-files/single-file-elixir-scripts/, SamplePhoenix do
    pipe_through(:browser)

    dwell("https://fly.io/"https://fly.io/phoenix-files/single-file-elixir-scripts/, SampleLive, :index)
  finish
finish

defmodule SamplePhoenix.Endpoint do
  use Phoenix.Endpoint, otp_app: :pattern
  socket("/dwell"https://fly.io/phoenix-files/single-file-elixir-scripts/, Phoenix.LiveView.Socket)
  plug(Router)
finish

{:okay, _} = Supervisor.start_link([SamplePhoenix.Endpoint], technique: :one_for_one)
Course of.sleep(:infinity)

Seems the bug wasn’t in Phoenix in any respect and was an oopsie on my half. Can you notice it?

This one is barely extra concerned and relies on the wojtekmach/mix_install_examples venture. With this file you’ve got a completely practical Phoenix LiveView utility in a single file operating on port 5001!

And you’ll see all the stuff you want to make Phoenix Work, and albeit it isn’t that a lot. When folks say we want a “light-weight net framework” ask them what’s pointless on this file!

Report Fly.io Issues

Here at Fly.io we try to be super responsive on the questions on our community forum. For instance we’ve a problem with utilizing mnesia and fly volumes, like some customers recently posted. If we needed to publish an remoted bug report, we might arrange a minimal venture to assist actually get the eye of the help group.

First, we might need a Dockerfile that may run Elixir scripts

# syntax = docker/dockerfile:1
FROM "hexpm/elixir:1.14.2-erlang-25.2-debian-bullseye-20221004-slim"

# set up dependencies
RUN apt-get replace -y && apt-get set up -y build-essential git libstdc++6 openssl libncurses5 locales 
    && apt-get clear && rm -f /var/lib/apt/lists/*_*

# Set the locale
RUN sed -i '/en_US.UTF-8/s/^# //g' /and so on/locale.gen && locale-gen

# Env variables we would need
ENV LANG en_US.UTF-8
ENV LANGUAGE en_US:en
ENV LC_ALL en_US.UTF-8
ENV ECTO_IPV6 true
ENV ERL_AFLAGS "-proto_dist inet6_tcp"

WORKDIR "/app"

# Copy our recordsdata over
COPY bug.exs /app

# set up hex + rebar when you plan on utilizing Combine.set up
RUN combine native.hex --force && 
    combine native.rebar --force

CMD elixir /app/bug.exs

Lastly add our bug.exs

vol_dir = System.get_env("VOL_DIR"https://fly.io/phoenix-files/single-file-elixir-scripts/) || "/knowledge"

# Setup mnesiua
Software.put_env(:mnesia, :dir, to_charlist(vol_dir))
:okay = Software.begin(:mnesia)

# Examine that mnesia is working
dbg(:mnesia.change_table_copy_type(:schema, node(), :disc_copies))

# Perhaps attempt writing a file to see whatsup
path = Path.be part of([vol_dir, "hello.txt"https://fly.io/phoenix-files/single-file-elixir-scripts/])
File.write!(path, "Hi there from elixir!"https://fly.io/phoenix-files/single-file-elixir-scripts/)
IO.places(File.learn!(path))

Course of.sleep(:infinity) # Hold it operating so fly is aware of its okay

And our fly.toml

See Also

app = "APP NAME"

[mounts]
supply = "knowledge"
vacation spot = "/knowledge"

Now we will fly create APP_NAME, fly volumes create knowledge, fly deploy after which verify the logs fly logs to see what failed.

On this case, I could not reproduce the error they had been seeing. However it’s useful to have some code that is remoted to solely the issue you’re having. We might additionally see beginning up a Phoenix server this fashion and deploying a weekend tiny app. I would not suggest it, however you possibly can!

In Conclusion

If you take nothing else away from this post, I hope you click around Wojtek Mach‘s FANTASTIC mix_install_examples repository for Elixir script inspiration. You are able to do absolutely anything from Machine Studying to low stage Methods Programming, all from a single file and the Elixir runtime.

And at last, please do not be afraid to make use of them as a growth instruments. For those who encounter a nasty bug in a library or your code, it will probably actually assist to isolate it to JUST the failing code and construct out a easy repeatable take a look at case like this.

Or possibly as a substitute of asking ChatGPT to jot down you a shell script, write it in Elixir, so a human can learn it.

Fly.io is a good way to run your Phoenix LiveView app near your customers. It is very easy to get began. You may be operating in minutes.

Deploy a Phoenix app today!  



Source Link

What's Your Reaction?
Excited
0
Happy
0
In Love
0
Not Sure
0
Silly
0
View Comments (0)

Leave a Reply

Your email address will not be published.

2022 Blinking Robots.
WordPress by Doejo

Scroll To Top