How to set value from url params without specifyng it in the request body?

I’m working with Ash and AshJsonApi and encountering an issue with how article_id is being handled in the URL parameters for my comment resource.

  actions do
    create :add_comment do
      accept [:comment, :article_id]

      change set_attribute(:article_id, arg(:article_id))
  end

My domain:

  json_api do
    routes do
      base_route "/articles", Article do
          base_route "/:article_id/add_comment", Comment do
            post :add_comment
        end
      end
    end
  end
end

I intended to use change set_attribute(:article_id, arg(:article_id)) in the add_comment action of the comment resource to automatically set the article_id from the URL parameters, without having to include it in the request body. However, I’m encountering an error where it says invalid_body and required properties are missing: channel_id

How can I configure Ash to use the article_id from the URL parameters for the add_comment action?

Assuming you want to create your comments by submitting POST request to /articles/:article_id/comments

Try changing this

actions do
    create :add_comment do
      accept [:comment, :article_id]

      change set_attribute(:article_id, arg(:article_id))
  end

to

actions do
    create :add_comment do
      argument :article_id, :uuid
      accept [:comment]

      change set_attribute(:article_id, arg(:article_id))
  end

Basically you set the arguments that you are accepting via URL placeholders via argument/2 and you set required body fields expected in your POST request via accept/1. Not sure if my interpretation is correct but that has worked for me.

2 Likes

on a different note, you might want to change the following

      base_route "/articles", Article do
          base_route "/:article_id/add_comment", Comment do
            post :add_comment
        end
      end

to

      base_route "/articles", Article do
          base_route "/:article_id/comments", Comment do
            post :add_comment
        end
      end

this would result in an url POST /api/articles/:id/comments for creating comments instead of POST /api/articles/:id/add_comments.

More than following some established conventions for the URLs, having the base_route as /:article_id/comments allows you to nest other actions like read :get_comment_by_id and get meaningful URLs. Otherwise as per your existing setup, a nested url to read comment would be GET api/articles/:article_id/add_comments/:id which is not meaningful.

1 Like