maliawelli

maliawelli

Hey,

I’ve got problem with has many association. I would like to connect posts with posts_likes through “post_id” and “user_id” (which would be took from guardian Guardian.Plug.current_resource(conn)). How can I do this? It is easily possible in SQL, but how to translate it to elixir and ecto?

In pseudo code it should look like:

SELECT posts, posts_favourites WHERE post.id = posts_favourites.post_id AND posts_favourites.user_id = Guardian.Plug.current_resource(conn).id

Showing Posts 1 to 10

maliawelli

maliawelli OP

Or if it’s not possible (but should be), I tried:

user = Guardian.Plug.current_resource(conn)
page = Post.preload
|> Repo.paginate(params)

a = Enum.reduce page.entries, %{}, fn x, entry ->
  user_id = user.id
  y = %{"favourite" => Repo.all(Post.getFavourites(x.id, user_id))}
  [y | x]
end

in model with getFavourites I download my favs for logged user. But this enum.reduce doesn’t work, could someone help me to fix this?

NobbZ

NobbZ

What do you mean by “doesn’t work”?

I do not see anything why it shouldn’t work, but probably it does “not return what you expect it to”.

  1. user_id is static, you do not need to set it in the reduce-function, you can move it to the outside or directly use user.id
  2. You are returning a list, consisting of a map %{"favourite" => …} as its first element and the current item as tail.
  3. you are discarding the previous accumulator (entry) and do not use it at all
  4. You start your accumulator as %{}, but then you make it an improper list, while this generally works it is inconsistent

So please show us some sample input (simplified), what your function returns and what you expect it to return instead.

This helps us to help you.

maliawelli

maliawelli OP

Thanks for your response.

Actually you are right. I do not get what I expect.

In my page.entries I’ve got something like (pseudocode):

posts => [post => [id => 1, title => 'test', 'user_id' => 2, 'comments' => ['user_id' => 2, 'post_id' => 1]]]

I would like to join to each post my favourites from %{"favourite" => Repo.all(Post.getFavourites(x.id, user_id))}

I’m coming from OOP language.
For instance in PHP it would be (again pseudocode):

for ($i = 0; $i < count(page.entries); $i++) {
page.entires[$i]['favourites'] = $this->getFavorite($post_id, $user_id);
}

Probably it is easy, but I can’t get it in elixir.

My purpose is to have information in each post if logged user have post in favourites.

NobbZ

NobbZ

This is a bad idea. Pseudocode isn’t standardized and with natural languages, everyone can interprete some things slightly different than you.

This forum is about elixir, so it is best to use elixir when writing code. But of course you can use any language you want, but please use those that do actually exist and use them sparse.

To be honest, I do not understand what that piece of pseudocode-data is. Is it a keywordlist, a map, a record, something else? Why do you have keys sometimes in quotes and sometimes not?


What I requested you for was, that you provide us input, expected output, actual output and your implementation in a simplified way, so that we can load it into iex and play around with it.

Just like this:

I have a function called inc, but it doesn’t seem to work.

My function looks like this:

def inc(x), do x - 1

I expect it to count up, but when I do inc(2) or inc(10) I do get 1 and 9 in return, while I expect it to be 3 and 11 respectively.

Can anyone help me solve this?

This example is of course overly simplified and the problem obvios, but it is just an example.


But now, lets try to help you.

As I do understand you, you have a list of things, where each thing is a map (or struct).

You want to iterate over those things and collect a list of maps with one key each. That should be roughly possible like this:

def get_favorites(posts) do
  Enum.map(posts, fn post ->
    %{"favourite" => Repo.all(Post.getFavourites(x.id, user_id))}
  end
end

But thats really only a quick guess.

Imperative for-loops which counter is used as an index in an assignment can often be translated into Enum.map/2, which makes the code much clearer.

maliawelli

maliawelli OP

You understood me clearly.

Here is my data structure:

In each post I would like to have information about “favourites” (only when user is logged), like for instance I’ve got information about comments, votes etc.

I modified your code a bit:

b = cond do
   current_user ->
       Enum.map(page.entries, fn post ->
         %{"favourite" => Repo.all(Post.getFavourites(post.id, current_user.id))}
       end)
       true -> page.entries
end

IO.inspect(b)

Probably it is fine, but I’ve got error:

"an exception was raised:
          ** (Poison.EncodeError) unable to encode value: {2, 1}"

And my getFavourites:

 def getFavourites(post_id, user_id) do
        from p in "posts_favourites",
            where: p.post_id == ^post_id and p.user_id == ^user_id,
            select: {p.post_id, p.user_id}
     end

Can you help me please?

Or mayby there is better method to fetch this data?

gregvaughn

gregvaughn

What’s happening here is the select in getFavourites is returning a two element tuple with {post_id, user_id}. Poison doesn’t know how to convert tuples to json. You can get something serializable, but probably still needing to be tweaked for your needs with:

select: %{post_id: p.post_id, user_id: p.user_id}

because that will be a map that Poison can handle

NobbZ

NobbZ

The screenshot(?) shows some arbitrary JSON(?).

In your elixir code you will probably not deal with that JSON directly, but with an represantation in elixir terms. Its much more important how those look.

maliawelli

maliawelli OP

Thank you, you were right. I’ve so much to learn with elixir.

Anyway this enum.map posted above doesn’t return expected data. It returns only:
> “posts”: [ { “favourite”: }, { “favourite”: [ { “user_id”: 1, “post_id”: 2 } ] } ]

So all post data is thrown out. How can I fix this?

And mayby @gregvaughn do you have better idea to fetch this data?

@NobbZ
Yes, because I return .json data with:

|> render(“index.json”, posts: b, page: page)

Is that incorrect?

gregvaughn

gregvaughn

You’re getting the data you are querying for. The problem appears to be your getFavourites query. It doesn’t implement this (incorrect) sql you asked about.

You probably want something more like:

from p in Post,
join: f in :posts_favourites, on: f.post_id == p.id and f.user_id == ^user_id

Note: I haven’t tested that out because I don’t know your schema, but hopefully it’ll get you closer. I’m assuming you want full post data returned and not just ids like you are currently selecting

NobbZ

NobbZ

Which is as expected according how I understood you. This is why I asked for input and output as you expect it in elixir syntax multiple times. I’m still waiting.

Nope, but irrelevant as well… After encoding json it’s just a string from elixir point of view, but we are somewhere before that, we are dealing with maps, tuples, lists, integers, floats, atoms and whatnots. Those are relevant for us.

Where Next? Top

Trending in Questions Top

katta
I having some trouble figuring out if I have set myself too strict of standards for my production server. Currently I can handle 75% of r...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
achenet
Hello, I’m trying to build a basic Phoenix web-app, and I’d like to use Tailwind. However, when I launch mix phx.server, I get an error...
New
kpanic
Hi everyone, I am toying with the idea of building a “match maker” for giving personal help to people that wants to start coding. I sta...
New
asweet-confluent
I recently noticed that Elixir’s Logger defaults its primary log level to :debug when no :logger, :level application configuration is pre...
New
Cxx-mlr
I’m working on a small exercise involving update_in/3, and I came up with this solution: data = %{ name: "Periodic Table", category:...
New
ChrisAmelia
I’ve got trouble wrapping my head around the order in which functions are called in this snippet (from Phoenix’s authentication): toke...
New

Other Trending Topics Top

GenericJam
Edit: 2026 May 15 - This post is archived. Mob is alive!! Main docs: mob v0.7.11 — Documentation A bit of explanation for the slightly c...
New
JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
garrison
Hobbes is a low-level distributed database for the Elixir programming language. Hobbes provides a simple, safe, and scalable storage lay...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
budgie
A little off-topic, but I feel like people here have a good head on their shoulders. I used to be quite good at making software. Was luc...
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews