September 13, 2016

Introducing my new book, Best Practices for Developing iOS Apps with Swift

Hey there!

That's right, I'm launching the first book in what I expect will be a long list of titles that I'll be publishing in the following months.

Best Practices for Developing iOS Apps with Swift, available late October, focuses on how to avoid the mistakes that I've already made, so you don't have to make them and your apps can be future-proof.

Register now to get get notified when the book launches. You'll get the first chapter for free when it's ready. Oh, also, a 50% off discount code on launch day.

Fun fact: this is actually the English version of the original book I wrote "Mejores Prácticas Del Desarrollo de Aplicaciones para iOS con Swift", which is going to be out by the end of the month. If you're interested, go check it out now.

Thanks for reading, and see you later!


September 08, 2016

› Tesla, the new HTTP client for Elixir

As I've written before in this blog, I've been playing with Elixir/Phoenix for the past few months — I even have a couple of production applications running right now!

Just learned about Tesla, a new HTTP client for Elixir. I've taken a quick look at it and it seems that's something I'll be using for my next proyects.

What I like the most is the plug based architecture that it uses to build clients. It relfects a lot the way I build HTTP clients with Swift, so it feels right.

If you're looking for a replacement for httpotion or httpoison, definitely take a look at this.


July 25, 2016

Filtering has_many relationships in Ecto

This is sot-of a follow up to my last post, about self-referencing many_to_many relationships using Ecto.

I find myself in a scenario where I have a User:

# User model
defmodule MyApp.User do  
  use MyApp.Web, :model

  alias MyApp.Contact

  schema "users" do
    has_many :_internal_contacts, MyApp.Contact
    has_many :contacts, through: [:_internal_contacts, :contact]

    timestamps
  end
end  

and an association model Contact through which the User has many contacts (User instances):

defmodule MyApp.Contact do  
  use MyApp.Web, :model

  alias MyApp.User

  schema "contacts" do
    field :status, :integer

    belongs_to :user, User, foreign_key: :user_id
    belongs_to :contact, User, foreign_key: :contact_id

    timestamps
  end

  def status_code(status) do
    case status do
      :accepted ->
        1
      :pending ->
        0
      :rejected ->
        -1
      _ ->
        0
    end
  end

I created an endpoint on my app that's supposed to get me only the user's contacts that have the :accepted status (1). How can this be accomplished?

The Repo module has a set of handy functions that let you preload associations on your models.

user = User |> Repo.get(1) |> Repo.preload(:contacts)  

The above will preload all contacts on the user. Pay attention to the fact that it is of type has_many and it goes through the :_internal_contacts property. This is the important cue.

Turns out that the preloads parameter on Repo.preload/3 can be accompanied by a query.

import Ecto.Query

#1
query = from c in Contact, where: c.status == 1 and c.user_id == 1

u = User  
    |> Repo.get(1) #2
    |> Repo.preload(_internal_contacts: query) #3
    |> Repo.preload(:contacts) #4

The code above will:

  1. Create a query that will ask for Contacts with status 1 and with user_id 1.
  2. Get a User instance.
  3. Preload the _internal_contacts on that instace using our query (these are Contact instances, not User instances)
  4. Preload the :contacts on our user. And since :contacts goes through: _internal_contacts, :contacts has only valid contacts now (User instances).

Notes:

Honestly, I don't know if this is the right approach here (let me know!). I did find this thread on GitHub where the general issue that we're facing here is described. It seems that there's an interest to have the ability to filter the relationships on the declaration itself:

It would look something like this:

has_many :comments, MyApp.Comment, foreign_key: :commentable_id,  fn (query) ->  
  from c in query, where: c.commentable_type == "articles"
end  

However, right now, the saner approach seems to be the use of composable queries.

Have anything to add to this article or did I miss something? Please let me know on Twitter.


July 23, 2016

Self-referencing many-to-many relationships using Ecto

EDIT: I've changed the last section of this article to reflect my findings in actually using this in production.


I've decided to do the backend for a new app I'm creating myself, using Elixir/Phoenix. I've been learning Elixir for the past few months and thought it would be a great opportunity to put what I've learned to good use.

There's a lot of documentation about the new many_to_many macro in Ecto 2 — but somehow, it still was a bit of a pain to get this right the first time. I couldn't find a concrete example of how a self-referencing many-to-many relationship would work with Ecto, and after some digging and the help of the awesome Elixir community, I got it working. I'm writing this post just to put this out there so you can go through this quicker.

In the app, a User can have contacts, which are themselves Users. (Let's omit the authentication stuff for now) The migration looks like this:

# priv/repo/migrations/create_users_table.ex
defmodule MyApp.Repo.Migrations.CreateUsersTable do  
  use Ecto.Migration

  def change do
    create table(:users) do
      add :username, :string
    end

    create unique_index(:users, [:username])
  end
end  

Then, the module that defines the schema looks like this:

defmodule MyApp.User do  
  use MyApp.Web, :model

  schema "users" do
    field :username, :string

    timestamps
  end

  # Omitting changesets
end  

In order to create a many-to-many relationship correctly we must have an associative table, that we'll call "contacts". This is the migration for that:

defmodule MyApp.Repo.Migrations.CreateContactsTable do  
  use Ecto.Migration

  def change do
    create table(:contacts) do
      add :user_id, references(:users, on_delete: :nothing), primary_key: true
      add :contact_id, references(:users, on_delete: :nothing), primary_key: true
      add :status, :int

      timestamps()
    end
  end
end  

To expand a bit, the "Contacts" table has... :

  1. a column user_id, which is the id for the user that initiated the "friend request".
  2. a column contact_id, which is the id for the user that must accept or reject the "friend request"
  3. a column status, which represents the friendship status (0=pending, 1=accepted, -1=rejected).

Now for the interesting part, we have to create a "Contacts" schema that Ecto can work with in order for the association to work correctly. On to it:

defmodule MyApp.Contact do  
  use MyApp.Web, :model

  alias MyApp.User

  schema "contacts" do
    belongs_to :user, User
    belongs_to :contact, User
  end
end  

We define the Contact module, that belongs to both a user and a contact, both being User types. We now have to update the User model to reflect the many-to-many relation:

defmodule MyApp.User do  
  use MyApp.Web, :model

  schema "users" do
    field :username, :string
    # Add the many-to-many association
    many_to_many :contacts, MyApp.User, join_through: "contacts", on_replace: :delete
    timestamps
  end

  # Omitting changesets
end  

Using the many_to_many macro we only have to specify the field on the User model, tell Ecto what table use as association table, and that's it!

You can now do this in your code:

user = Repo.get(User, 1) |> Repo.preload(:contacts)  
contact = hd(user.contacts)  

However...

A member of the Elixir community told me on Slack that this looks more like a one-to-many relationship, and that I should try to represent it that way in my app. It would look like this:

defmodule MyApp.User do  
  use MyApp.Web, :model
  alias MyApp.Contact

  schema "users" do
    field :username, :string
    # Add the many-to-many association
    has_many :_contacts, MyApp.Contact
    has_many :contacts, through: [:_contacts, :contact]
    timestamps
  end

  # Omitting changesets
end  

It works, however I don't like the fact that now we basically have cluttered our model, having _contacts and contacts in it. Then there's the fact that Ecto models are just backed by a simple struct, so there's no way to "hide" details about it (as-in: make _contacts private). I decided to stick with the many_to_many version of this code because it hides the association table quite nicely.

After playing with this for a bit, I realised that this is the correct approach, although it clutters the user instance space.

During actual testing in my Phoenix app, I noticed that the query that Ecto was generating with the former association type was the wrong one. Switching it from many_to_many to has_many as above, fixed the issue.

Have something to add to this article, or did I miss something? Hit me up on Twitter.