laravel-json-api / laravel

JSON:API for Laravel applications
MIT License
541 stars 41 forks source link

Error in JsonApiRule::toOne #292

Closed Yeleup closed 2 months ago

Yeleup commented 2 months ago

request

'giver' => ['required', JsonApiRule::toOne()],
'recipient' => ['required', JsonApiRule::toOne()],

schema

BelongsTo::make('giver'),
BelongsTo::make('recipient'),

model

    public function giver(): BelongsTo
    {
        return $this->belongsTo(Customer::class, 'giver_id');
    }

    public function recipient(): BelongsTo
    {
        return $this->belongsTo(Customer::class, 'recipient_id');
    }

When I create I get

 "errors": [
        {
            "detail": "The giver field must be a to-one relationship containing givers resources.",
            "source": {
                "pointer": "/data/relationships/giver"
            },
            "status": "422",
            "title": "Unprocessable Entity"
        },
        {
            "detail": "The recipient field must be a to-one relationship containing recipients resources.",
            "source": {
                "pointer": "/data/relationships/recipient"
            },
            "status": "422",
            "title": "Unprocessable Entity"
        }
    ]
ben221199 commented 2 months ago

Show your request too.

Yeleup commented 2 months ago

Show your request too.

class InvestmentRequest extends ResourceRequest
{

    /**
     * Get the validation rules for the resource.
     *
     * @return array
     */
    public function rules(): array
    {
        return [
            'giver' => ['required', JsonApiRule::toOne()],
            'recipient' => ['required', JsonApiRule::toOne()],
            'value' => ['required', 'numeric'],
            'rate' => ['required', 'numeric'],
            'currency' => ['required', Rule::in(['USD', 'EUR'])],
        ];
    }
}

request

$data = [
            'type' => 'investments',
            'attributes' => [
                'value' => 1000,
                'currency' => 'EUR',
                'rate' => 0.01,
            ],
            "relationships" => [
                'giver' => [
                    "data" => [
                        "type" => 'customers',
                        "id" => (string) $this->giver->getRouteKey(),
                    ],
                ],
                'recipient' => [
                    "data" => [
                        "type" => 'customers',
                        "id" => (string) $this->recipient->getRouteKey(),
                    ]
                ],
            ]
        ];

        $response = $this
            ->withToken($this->user->createToken('ApiToken')->plainTextToken)
            ->actingAs($this->user)
            ->jsonApi()
            ->expects('investments')
            ->withData($data)
            ->post('/api/v1/investments');

        $response->assertStatus(Response::HTTP_CREATED);
ben221199 commented 2 months ago

And your schema.

Yeleup commented 2 months ago

And your schema.


public function fields(): array
    {
        return [
            ID::make(),
            BelongsTo::make('organization'),
            BelongsTo::make('user'),
            BelongsTo::make('giver'),
            BelongsTo::make('recipient'),
            HasMany::make('transactions'),
            Number::make('value'),
            Number::make('rate'),
            Str::make('currency'),
            Str::make('reference')->sortable(),
            DateTime::make('startedAt')->sortable(),
            DateTime::make('receivedAt')->sortable(),
            DateTime::make('createdAt')->sortable()->readOnly(),
            DateTime::make('updatedAt')->sortable()->readOnly(),
        ];
    }
Yeleup commented 2 months ago

I've decided through

BelongsTo::make('giver')->type('customers')
BelongsTo::make('recipient')->type('customers'),
lindyhopchris commented 2 months ago

Yeah that looks right because of this: https://laraveljsonapi.io/docs/3.0/schemas/relationships.html#inverse-type

Please close if this is now working.