wintermeyer

wintermeyer

How to create a like action?

I have a Reaction resource which is used to store likes and blocks in a social media context (a user can like an other user). I want to create a like action but get the following error. How can I fix this?

iex(12)> like = Animina.Accounts.Reaction 
|> Ash.Changeset.for_create(:like, %{sender_id: user2.id, receiver_id: stefan.id}) 
|> Animina.Accounts.Reaction.create!()
** (Protocol.UndefinedError) protocol Enumerable not implemented for #Ash.Changeset<action_type: :create, action: :like, attributes: %{sender_id: "207a829e-2464-42f7-8257-f4fa482fc7c2", receiver_id: "096da9ff-bcf7-49a1-8cba-f98413f37cab"}, relationships: %{},

The resource:

defmodule Animina.Accounts.Reaction do
  @moduledoc """
  This is the Reaction module which we use to manage likes, block, etc.
  """

  use Ash.Resource,
    data_layer: AshPostgres.DataLayer

  attributes do
    uuid_primary_key :id

    attribute :name, :atom do
      constraints one_of: [:like, :block]
      allow_nil? false
    end

    create_timestamp :created_at
  end

  relationships do
    belongs_to :sender, Animina.Accounts.User do
      allow_nil? false
      attribute_writable? true
    end

    belongs_to :receiver, Animina.Accounts.User do
      allow_nil? false
      attribute_writable? true
    end
  end

  actions do
    defaults [:create, :read, :destroy]

    create :like do
      accept [:sender_id, :receiver_id]
      change set_attribute(:name, :like)
    end
  end

  code_interface do
    define_for Animina.Accounts
    define :read
    define :create
    define :destroy
    define :by_id, get_by: [:id], action: :read
    define :by_sender_id, get_by: [:sender_id], action: :read
    define :by_receiver_id, get_by: [:receiver_id], action: :read
  end

  identities do
    identity :unique_reaction, [:sender_id, :receiver_id, :name]
  end

  postgres do
    table "reactions"
    repo Animina.Repo

    references do
      reference :sender, on_delete: :delete
      reference :receiver, on_delete: :delete
    end
  end
end

First Post!

benswift

benswift

Looks like you are mixing up the changeset-based resource creation flow and the code interface one. Once you have a changeset, you just pipe it into ‘Ash.create!’.

Sorry about the terse reply, typing on my phone right now :slight_smile:

Most Liked

zachdaniel

zachdaniel

Creator of Ash

You have a :like action, and so how you call it in code can’t and won’t affect how the JSON:API behaves (which is why Ash is the way that it is).

There are three ways to call this like action in code, one of which is no longer available in 3.0. AshJsonApi will be unaffected by your choice here. You should choose #1, but I’m including 2 & 3 informationally.

  1. You can define a code interface function as @joelpaulkoch says. This is the recommended approach. For this, you’d define something like this:
define :like, args: [:sender_id, :receiver_id]

and call it like YourResource.like(sender_id, receiver_id).

NOTE: In 3.0 this can be done in one additional way, where you define the code interface on the domain. It’s not relevant here, see the upgrade guide for more.

  1. You can build a changeset and then call YourApi.create not YourApi.Resource.create. This is deprecated in 3.0

  2. You can build a changeset and then call Ash.create. However, this only works if you have configured an api when using the resource, i.e use Ash.Resource, api: Api. (because we have to know the api). This is essentially a compatibility feature to make upgrading to 3.0. Don’t bother with it right now. When you are interested in upgrading to 3.0, the upgrade guide will explain how to make this change.

benswift

benswift

Oops, sorry – I have been working on v3 stuff and forgot to switch my brain out of that gear :slight_smile:

Where Next?

Popular in Questions Top

RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
vonH
In asking this question I am more interested about the expressiveness of the language itself and less concerned about the availability of...
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New

Other popular topics Top

nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
New
hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" =&gt; #BSON.ObjectId&lt;58eb1a7a9ad169198c3dXXXX&gt;, "email" =&gt; ...
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
New
JorisKok
I have a server on AWS, and was running a load test using artillery. When looking at the Phoenix dashboard I see the Ports going to 100% ...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New

We're in Beta

About us Mission Statement