Image for post
Image for post
many to many

In my application to search for rooms I have added some features in room. Like availity of parking space, Internet, pets friendly, kids friendly and some more. When adding the rooms for rent user will have check the check box to indicate the availability of the features. This features will further mapped to the many to many relation in our database.

Node: I have added common pitfalls and their solution at the last.

mix phx.gen.context Amenities Amenity amenities name

Before migrating let’s add unique constraint in the migration file

mix ecto.migrate

I already Had a Rooms Context and its schema (schema shown below), Next I generated juction table called…


Image for post
Image for post
Migrations

Make a field nullable

mix ecto.gen.migration add_nullable_to_field

def change do
alter table(:events) do
modify(:title, :string, null: true, from: :string) # Title column is now nullable
end
end

Add field to existing table

mix ecto.gen.migration add_is_super_admin_to_merchant

Add references to existing table

mix ecto.gen.migration add_district_id_to_room

defmodule Tailwind.Repo.Migrations.AddedDistrictIdToRoom do   use Ecto.Migration
def change do
alter table :rooms do
add :district_id, references( :districts, on_delete: :delete_all)
end
end
end

Add Unique index to a field

I forgot to add unique constraint in email. so generating a migration to add constraint in email.

mix ecto.gen.migration add_uniq_constraint_to_email_on_merchant

Then do mix ecto.migrate

if you got error like “Key (email)=(abc@abc.com) is duplicated.”, that means you already have multiple values in database of same email. Remove those duplicate values and run the migrate command again.

We also need to add unique constraint for email in model .


Image for post
Image for post

While in mobile application we needed to install sdk for google maps, I found it somewhat similar in the web too. Easy part is that we can add it via cdn. And hard part is that we have to use Javascript. :) But It was not that hard though.

<div class="w-1/4 h-70">
<div id="googleMap" style="width:100%;height:400px;"></div></div>

I created div with id equal to googleMap

Then in script below just added this.

<script>    function myMap() {    var mapProp = {      center: new google.maps.LatLng(51.508742, -0.120850),      zoom: 5,    };    var map = new google.maps.Map(document.getElementById("googleMap"), mapProp);}
</script>
<script src="https://maps.googleapis.com/maps/api/js?key=YOUR_KEY&callback=myMap"></script>

We need key for googlmaps to work otherwise we can pass empty to start in development…


Small elixir snippets that actually works, now thats called fun.

Image for post
Image for post
Automations

Automating tedious jobs are sure fun. I am writting an Roomfinder application as a part of my through learning elixir, phoenix and web development as a whole.

I am from Nepal. Nepal has 77 district and 7 States. I needed to create a database table from it.

All districts and corresponding states of Nepal

I added above json file in priv/static/json/district_list.json

Then generated context using

mix phx.gen.context Districts District districts name state:integer

mix ecto.migrate

Then in seeds.exs file I added a script to read the file and loop through all and insert it to database.

And thats it without any error all address are now inside my postgres database.


Phoenix Auth Has never been so simple

I already written how to add social authentication in phoenix

But for email password authenitcation Its amazingly simple now.

Image for post
Image for post
Authentication

open mix.exs and add deps.

{:phx_gen_auth, “~> 0.6.0”}

Then run,

mix phx.gen.auth Accounts User users

mix ecto.migrate

and thats it. We have full fledge authentication system.

run the server and try it in the browser

http://localhost:4000/users/log_in

you should see login page.

Bonus:

To guard a routes we can pass scope through the require_authenticated_user plug. It is already in our route file generate by phx_gen_auth

pipe_through [:browser, :require_authenticated_user]

To guard a specific action in controller

import TailwindWeb.UserAuth, only: [require_authenticated_user: 2]plug :require_authenticated_user when action in [:my_rooms, :new, :edit, :delete]

Image for post
Image for post
google facebook login

Authentication is always hard for someone new in the field. But once we do it, Oh.. It feels good.

I had experience with social authentication in mobile application. So I had some faint concept, But this is my first time doing social authentication with web. I did got into unexpected handshake errors which was really hard to debug. Will tell about this at the end. First let’s get started.

First let’sueberauth_facebook and ueberauth_google as dependency

def deps do
[{:ueberauth_facebook, "~> 0.8"}],
{:ueberauth_google, "~> 0.10"},end

mix deps.get

Then configured ueberauth for facebook strategy in config.exs . …


Image for post
Image for post
Old Database

Since I am learning Elixir and phoenix, I thought tinker with my web app I already had up with Nodejs. I used Sequelize with nodejs and my table had column names as camelCase. But Ecto, by default follows the snake_case convention. But Integrating was quite easy and painless.

I generated Account models with mix

phx.gen.html Accounts User users email f_id g_id

deleted the migration file generated.

And updated the schema as follows:

schema "users" do    field :email, :string    field :fb_id, :string    field :g_id, :string    field :name, :string    field :inserted_at, :utc_datetime, source: :createdAt    field :updated_at, :utc_datetime, source: :updatedAt# timestamps()end

I had problem with timestamps. …


Image for post
Image for post
Jquery

Adding Jquery may seems like trival but for someone not from web platform, I really did Felt the fatigue, hunting solution for hours and hours. It was like walking an unknown territory in complete dark, sometimes there were faint light shown by stackoverflow, github and google. But there were also pitch dark times when I, alone, went deep inside the forest of my inexperiences. But finally, once I got that final missing link, It turned out to be quite simple. And ultimately became trivial for me too.

cd assets and do yarn add jquery

open webpack.config.js and add the following.

const webpack =…


Image for post
Image for post
Font Awesome

inside assets folder

yarn add @fortawesome/fontawesome-free

yarn add file-loader

in assets/css/ create a file called _variables.scss add the following line.

$fa-font-path: "~@fortawesome/fontawesome-free/webfonts";

import following in app.scss file.

@import "variables";@import "@fortawesome/fontawesome-free/scss/brands";@import "@fortawesome/fontawesome-free/scss/regular";@import "@fortawesome/fontawesome-free/scss/solid";@import "@fortawesome/fontawesome-free/scss/fontawesome";

If you dont have sass-loader inside rules, in webpack.config.js, add it now

{    test: /\.[s]?css$/,    use: [       MiniCssExtractPlugin.loader,       'css-loader',       'sass-loader',       'postcss-loader'     ],}

Also while in webpack.config.js, lets configure the file-loader to load fontawesome

{    test: /\.(woff(2)?|ttf|eot|svg)(\?v=\d+\.\d+\.\d+)?$/,    use: [        {        loader: 'file-loader',        options: {            name: '[name].[ext]',            outputPath: '../fonts'        }      }   ]},

Add fontawesome icon in app.html.eex. and test it

<i class=”fas fa-bars”></i>

we should see this icon


We will also add tailwind forms and tailwind-aspect-ratio for working with images.

Image for post
Image for post

mix phx.new tailwind

cd assets

yarn add --dev autoprefixer postcss postcss-loader postcss-import tailwindcss

create a file postcss.config.js inside assets directory

// postcss.config.js

module.exports = {
plugins: [
require('tailwindcss'),
require('autoprefixer')
]
}

open webpack.config.js and change sass-loader to postcss-loader

{  test: /\.[s]?css$/,    use: [      MiniCssExtractPlugin.loader,      'css-loader',      'sass-loader',      'postcss-loader'    ],}

open app.scss and delete all content. and add

@import "tailwindcss/base";@import "tailwindcss/components";@import "tailwindcss/utilities";

inside assets directory, run (optional)

npx tailwind init --full // --full is optional too

this will generate a tailwind.config.js file which you can use to extend the tailwindcss if necessary (we will use it to add a form…

About

Sis Ccr

Depths of ocean could not swallow me.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store