2013-07-11

Elixir + MongoDB = SMART! Just like a chap...

 + 


What do you want to do every time you test a new programming language?

- connect to a db, obviously

But when you are using something as new as elixir (please note we don't even have a 1.0 yet) that can be some sort of challenge.
Also I came from Microsoft world, programming open source things in a mac is a whole new world to me
OK, not that new, it has been over 1 year now, but you have to realise I started programming VB in 1998 (god I feel old now!)

Anyway, back to it. You want to connect to a DB, but you don't have drivers for Elixir. 
What do you do, sit in the corner of the room and cry like a little girl?
No little grasshopper, keep in mind elixir run on erlang vm, you are in erlang's world now!

So, how do we do that?
we chop it into pieces - like our old chap Jack would say.

Part 0 - What you have to have before this

Start your mongodb (go to the folder and type sudo ./mongod)
Sounds obvious, but you would be amazed how often the obvious is forgotten.


Part 1 - Make sure you can connect to it

I like to always isolate the small bits to make sure they work separately, nothing better than using the iex for that.
download the driver
git clone https://github.com/mongodb/mongodb-erlang mongodb
go to the folder you just created and type 
make

now go to the ebin folder, open iex but add some extra parameters to add bson's ebin in the path as well

cd ebin
iex -pa ../deps/bson/ebin

now you are ready to start

:application.start(:bson)
:application.start(:mongodb)
{ :ok, conn } = :mongo_connection.start_link({:localhost, 27017}, [])
result = :mongo.do(:safe, :master, conn, :db, fn() -> :mongo.count(:test, []) end )

if everything went fine you should get the counting of documents you have in the collection test in the database db

great, now lets make it into an app!

Part 3 - Make it into an app

to create an app just type 
mix new /path/to/your/project

now edit your mix.exs to include the dependencies you have
This failed for me every time I added the git urls, so what I did was to clone them into the folder deps, make (just like above) and then added them in the mix.exs with the path :

  defp deps do
    [ {:bson, path: "deps/mongodb/deps/bson", override: true },
      { :mongodb, path: "deps/mongodb" } ]
  end

then all you have to do is to add the code to your app:

defmodule YourApp do
:application.start(:bson)
:application.start(:mongodb)

{ :ok, conn } = :mongo_connection.start_link({:localhost, 27017}, [])
result = :mongo.do(:safe, :master, conn, :db, fn() -> :mongo.count(:test, []) end )
IO.puts "You have #{result} documents in your collection"
end

go back to shell, run
mix deps.get
mix deps
to make sure they're all ok
mix run



Don't be sad if your result is 0, that just means you don't have any documents.
you can add them with:
:mongo.do(:safe, :master, conn, :db, fn() -> :mongo.insert(:test, [{:id, 1, :title, "test", :body, "testing post"}]) end )    

that is it, now you have an app that can access mongodb

Lets just go over some details to keep in mind:

when using erlang libs in elixir, so you can go in the original library help (in this case http://api.mongodb.org/erlang/mongodb/ )and use it with some little changes

mongo:do(safe, master, Conn, db, fun() -> mongo:insert(test, [ {id,1, title, "test" ]) end). 
becomes
:mongo.do(:safe, :master, conn, :db, fn() -> :mongo.insert(:test, [{:id, 1, :title, "test", :body, "testing post"}]) end )

  • erlang libs are atoms in elixir, and because of that you use :mongo
  • instead of : you use . to get functions
  • all the symbols should have : in front
  • variables doesn't have to start with capital letters
  • fn() instead of fun()
  • you have to use double quotes for strings. single quotes means array of integers
  • no . in the end


but that is it

coming up next: make this a web app

See you lads, 
have a good one!



Notes:
  • Special thanks to José Valim and Alexei Sholik who helped me to make this mongodb driver work
  • For those who didn't get the reference in the title... check Mr.B The Gentleman Rhymer