Elixir Phoenix Plugs #88 - JSToElm
All Episodes

Elixir Phoenix Plugs #88

Gotta admit, once I got the auth working and the deployment going, I was a bit hesitant to start adding to the project again. Because that meant, failed builds, unknown errors, and a general sense of failing. We just got things working! But's the sayin' "if it's not broken, you're not working hard enough"? So back at it I guess.

The layout and details

  • Routes

    • /
    • root of the app will eventually be an aggregate of incoming from Micro.Blog + our own feed (maybe)
    • /profile
    • ‘Settings’
    • this is where we’ll be able to add targets for our re-posting feature ‘echo’
    • add token keys and incorporate 3rd party API’s
    • /profile/posts
    • list of current users posts
    • /posting
    • this is the ‘editor’ with fields for title and content
    • Successful ‘post’ returns the user to an updated list of posts

Authorization

  • now that we have authentication out of the way. Let’s deal with only that user can post to that users account.

Just do it already!

 MB:postit> mix phx.gen.html Posting Post posts title:string content:text                                                                                                                     * creating lib/postit_web/controllers/post_controller.ex                                                                                                                                      * creating lib/postit_web/templates/post/edit.html.eex                                                                                                                                        * creating lib/postit_web/templates/post/form.html.eex                                                                                                                                        * creating lib/postit_web/templates/post/index.html.eex                                                                                                                                       * creating lib/postit_web/templates/post/new.html.eex                                                                                                                                         * creating lib/postit_web/templates/post/show.html.eex                                                                                                                                        * creating lib/postit_web/views/post_view.ex                                                                                                                                                  * creating test/postit_web/controllers/post_controller_test.exs                                                                                                                               * creating lib/postit/posting/post.ex                                                                                                                                                         * creating priv/repo/migrations/20190717045929_create_posts.exs                                                                                                                               * creating lib/postit/posting.ex                                                                                                                                                              * injecting lib/postit/posting.ex                                                                                                                                                             * creating test/postit/posting_test.exs                                                                                                                                                       * injecting test/postit/posting_test.exs                                                                         Add the resource to your browser scope in lib/postit_web/router.ex:                                    resources "/posts", PostController                          
remember to update your repository by running migrations:                                                                                                                                                  $ mix ecto.migrate                                                                                    MB:postit>  

That didn’t take long. Our first error. 😭

assign @current_user not available in eex template.
  • so it looks like we’ve hit an error in the form that is created when we ran the generator.
  • we’d forgotten to add the security plug to get for auth and the conditional in our Navbar is looking for current_user in order to render the login or logout buttons. happy that was simple.

    • The question is now, I have defined the secure function twice for both events and posts. Is there a place for those types of functions that i will be using in multiple controllers?
    • Option 1 seems to be helpers
    • Option 2 as found in Chris Bell Sharing Methods between controllers
    • Turns out the web.ex file has this cool macro __using__
def controller do
    quote do
      use Phoenix.Controller, namespace: PostitWeb

      import Plug.Conn
      import PostitWeb.Gettext
      alias PostitWeb.Router.Helpers, as: Routes
    end
  end
  • Create a controller helper and add it in here!

    • I ended up with a ‘controller helper’ and accidently build a plug

Plugs: what did i learn [dot] info

  • plugs feel conceptually a lot like express middleware, where it takes the connection or request and does a function on it, then returns the conn / request for the next plug or middleware
  • There are two types of plugs in the Phoenix. They are module plugs and function plugs. We are going to cover both of them in this article.

    • module has init and call
    • HAHAH we had a function plug, I just had no idea that is what it was or called
  • Where do we want the plug triggered?
  • having stumbled into it in an effort to ‘DRY’ out our code. And really, there will probably be more controllers in our app over time and I feel like I have really hit the sweet spot of learning

    • question - how do i reuse a function in multiple controllers
    • start with a helper
    • add it to the web.ex for controller that is called as a macro for every controller to import the helper
    • use that helper function on a plug for the controller,
    • just make it a plug function or module

Alias vs Import

  • What is the difference between alias and import ?

    • Docs! straight to the point doc alias
    • they are referred to as directives
    • alias use shorter name instead of the fully qualified name or prefix

      • is also lexically scoped, so it’s only available in the block / function you define it
      • “An alias in Elixir is a capitalized identifier (like String, Keyword, etc) which is converted to an atom during compilation. For instance, the String alias translates by default to the atom :"Elixir.String":”
    • require require this module in order to use it’s macros
    • import import functions from module so you don’t have to use the prefix
    • (macro) use invokes the custom code defined in that module as an extension point

Terms

  • changeset

    • possibly an ecto term?
  @doc false
  def changeset(post, attrs) do
    post
    |> cast(attrs, [:title, :content])
    |> validate_required([:title, :content])
  end
  • conn

    • Short for … connection
  • defp

    • Inside a module, we can define functions with def/2 and private functions with defp/2. A function defined with def/2 can be invoked from other modules while a private function can only be invoked locally.

Picks

Resources

Elixir Casts Pheonix Contexts

Alchemist Camp

Elixir Phoenix Realworld

Pheonix Conn CheatSheet

indieweb

Micro [dot] Blog

Follow

Published 25 Jul 2019

A show about learning Elm, Functional Programing, and generally leveling up as a JS developer.
JavaScript To Elm on Twitter