### FetchRequest Class - JavaScript Examples
Source: https://context7.com/rails/request.js/llms.txt
Demonstrates the usage of the FetchRequest class for making various HTTP requests in JavaScript. Includes examples for POST with JSON, GET with query parameters, file uploads with FormData, and cancelable requests using AbortController.
```javascript
import { FetchRequest } from '@rails/request.js'
// Basic POST request with JSON body
async function createUser() {
const request = new FetchRequest('post', '/users', {
body: JSON.stringify({
user: {
name: 'John Doe',
email: 'john@example.com'
}
}),
contentType: 'application/json'
})
const response = await request.perform()
if (response.ok) {
const data = await response.json
console.log('User created:', data)
return data
} else {
console.error('Failed with status:', response.statusCode)
throw new Error('User creation failed')
}
}
// Request with query parameters and custom headers
async function searchUsers() {
const request = new FetchRequest('get', '/users', {
query: {
search: 'John',
page: 1,
per_page: 20
},
headers: {
'X-Custom-Header': 'custom-value'
},
responseKind: 'json'
})
const response = await request.perform()
const users = await response.json
return users
}
// Upload file with FormData
async function uploadAvatar(file) {
const formData = new FormData()
formData.append('avatar', file)
formData.append('user_id', '123')
const request = new FetchRequest('post', '/avatars', {
body: formData
// Content-Type is automatically set for FormData
})
const response = await request.perform()
return response.ok
}
// Using signal for request cancellation
async function cancelableRequest() {
const controller = new AbortController()
const request = new FetchRequest('get', '/long-running-task', {
signal: controller.signal
})
// Cancel after 5 seconds
setTimeout(() => controller.abort(), 5000)
try {
const response = await request.perform()
return await response.json
} catch (error) {
console.log('Request cancelled or failed:', error)
}
}
```
--------------------------------
### Perform POST Request and Handle Response (JavaScript)
Source: https://github.com/rails/request.js/blob/main/README.md
This example shows how to instantiate a FetchRequest for a POST request, send it, and await the response. It highlights a known issue with Turbolinks where the `redirected` property will always be false.
```javascript
const request = new FetchRequest('post', 'localhost:3000/my_endpoint', { body: JSON.stringify({ name: 'Request.JS' }) })
const response = await request.perform()
response.redirected // => will always be false.
```
--------------------------------
### Install Rails Request.JS with npm or yarn
Source: https://github.com/rails/request.js/blob/main/README.md
Instructions for installing the @rails/request.js package using npm or yarn for use with Webpacker or Esbuild.
```shell
npm i @rails/request.js
```
```shell
yarn add @rails/request.js
```
--------------------------------
### Request Options Configuration in JavaScript
Source: https://github.com/rails/request.js/blob/main/README.md
Illustrates how to pass various options to the request methods, including body, contentType, headers, credentials, query parameters, responseKind, and keepalive. This example focuses on the structure of passing these options.
```javascript
post("/my_endpoint", {
body: {},
contentType: "application/json",
headers: {},
query: {},
responseKind: "html"
})
```
--------------------------------
### Shorthand HTTP Verb Methods in JavaScript
Source: https://github.com/rails/request.js/blob/main/README.md
Shows how to use the shorthand functions (get, post, put, patch, destroy) provided by @rails/request.js for making HTTP requests. This example illustrates a POST request and accessing the JSON response body.
```javascript
import { get, post, put, patch, destroy } from '@rails/request.js'
...
async myMethod () {
const response = await post('localhost:3000/my_endpoint', { body: JSON.stringify({ name: 'Request.JS' }) })
if (response.ok) {
const body = await response.json
...
}
}
```
--------------------------------
### Shorthand HTTP Methods
Source: https://context7.com/rails/request.js/llms.txt
Provides convenience functions for common HTTP verbs (get, post, put, patch, destroy) with a more concise syntax than directly using the Fetch API.
```APIDOC
## GET /api/users
### Description
Fetches a list of users, optionally filtering by active status.
### Method
GET
### Endpoint
`/api/users`
### Query Parameters
- **active** (boolean) - Optional - Filter for active users.
### Request Example
```javascript
import { get } from '@rails/request.js';
async function fetchUsers() {
const response = await get('/api/users', {
query: { active: true },
responseKind: 'json'
});
if (response.ok) {
return await response.json;
}
}
```
### Response
#### Success Response (200)
- **data** (array) - An array of user objects.
#### Response Example
```json
{
"users": [
{ "id": 1, "name": "Alice" },
{ "id": 2, "name": "Bob" }
]
}
```
```
```APIDOC
## POST /posts
### Description
Creates a new blog post with the provided title, content, and publication status.
### Method
POST
### Endpoint
`/posts`
### Request Body
- **title** (string) - Required - The title of the post.
- **content** (string) - Required - The main content of the post.
- **published** (boolean) - Optional - Whether the post should be published immediately.
### Request Example
```javascript
import { post } from '@rails/request.js';
async function createPost() {
const response = await post('/posts', {
body: {
title: 'New Post',
content: 'Post content here',
published: true
},
responseKind: 'json'
});
if (response.ok) {
const newPost = await response.json;
console.log('Created post ID:', newPost.id);
return newPost;
}
}
```
### Response
#### Success Response (201)
- **id** (integer) - The unique identifier of the newly created post.
- **title** (string) - The title of the post.
- **content** (string) - The content of the post.
- **published** (boolean) - The publication status.
#### Response Example
```json
{
"id": 101,
"title": "New Post",
"content": "Post content here",
"published": true
}
```
```
```APIDOC
## PUT /users/:userId
### Description
Updates an existing user's information with the provided data.
### Method
PUT
### Endpoint
`/users/:userId`
### Path Parameters
- **userId** (integer) - Required - The ID of the user to update.
### Request Body
- **updates** (object) - Required - An object containing the fields to update.
### Request Example
```javascript
import { put } from '@rails/request.js';
async function updateUser(userId, updates) {
const response = await put(`/users/${userId}`, {
body: updates,
contentType: 'application/json'
});
return response.ok;
}
```
### Response
#### Success Response (200)
- **success** (boolean) - Indicates if the update was successful.
#### Response Example
```json
{
"success": true
}
```
```
```APIDOC
## PATCH /users/:userId/toggle_status
### Description
Partially updates a user's status, typically to toggle between active and inactive.
### Method
PATCH
### Endpoint
`/users/:userId/toggle_status`
### Path Parameters
- **userId** (integer) - Required - The ID of the user whose status to toggle.
### Request Body
- **active** (boolean) - Required - The desired status (true for active, false for inactive).
### Request Example
```javascript
import { patch } from '@rails/request.js';
async function toggleUserStatus(userId) {
const response = await patch(`/users/${userId}/toggle_status`, {
body: { active: true },
responseKind: 'json'
});
return await response.json;
}
```
### Response
#### Success Response (200)
- **status** (string) - The new status of the user (e.g., 'active', 'inactive').
#### Response Example
```json
{
"status": "active"
}
```
```
```APIDOC
## DELETE /posts/:postId
### Description
Deletes a specific blog post.
### Method
DELETE
### Endpoint
`/posts/:postId`
### Path Parameters
- **postId** (integer) - Required - The ID of the post to delete.
### Request Example
```javascript
import { destroy } from '@rails/request.js';
async function deletePost(postId) {
const response = await destroy(`/posts/${postId}`, {
responseKind: 'json'
});
if (response.ok) {
console.log('Post deleted successfully');
return true;
}
return false;
}
```
### Response
#### Success Response (204)
- No content is returned upon successful deletion.
#### Response Example
(No body content)
```
```APIDOC
## General Error Handling
### Description
Demonstrates a robust pattern for handling various response statuses, including validation errors and network issues.
### Method
POST (example)
### Endpoint
`/api/endpoint`
### Request Body
- **data** (any) - Required - The data to send in the request.
### Request Example
```javascript
import { post } from '@rails/request.js';
async function robustRequest() {
try {
const response = await post('/api/endpoint', {
body: { data: 'value' },
responseKind: 'json'
});
if (response.ok) {
return await response.json;
} else if (response.statusCode === 422) {
const errors = await response.json;
console.error('Validation errors:', errors);
return { errors };
} else {
throw new Error(`Request failed: ${response.statusCode}`);
}
} catch (error) {
console.error('Network error:', error);
throw error;
}
}
```
### Response
#### Success Response (200)
- **data** (any) - The successful response data.
#### Error Response (422)
- **errors** (object) - An object containing validation errors.
#### Network Error
- Throws an error object.
#### Response Example (Success)
```json
{
"message": "Operation successful"
}
```
#### Response Example (Validation Error)
```json
{
"field_name": [
"Error message 1",
"Error message 2"
]
}
```
```
--------------------------------
### Implement Progress Bar with Request Hooks (JavaScript)
Source: https://github.com/rails/request.js/blob/main/README.md
This snippet demonstrates how to wrap a FetchRequest Promise with custom logic to display a progress bar before a request starts and hide it upon completion. It requires @rails/request.js and @hotwired/turbo.
```javascript
import { FetchRequest } from "@rails/request.js"
import { navigator } from "@hotwired/turbo"
function showProgressBar() {
navigator.delegate.adapter.progressBar.setValue(0)
navigator.delegate.adapter.progressBar.show()
}
function hideProgressBar() {
navigator.delegate.adapter.progressBar.setValue(1)
navigator.delegate.adapter.progressBar.hide()
}
export function withProgress(request) {
showProgressBar()
return request.then((response) => {
hideProgressBar()
return response
})
}
export function get(url, options) {
const request = new FetchRequest("get", url, options)
return withProgress(request.perform())
}
```
--------------------------------
### Shorthand HTTP Methods (JavaScript)
Source: https://context7.com/rails/request.js/llms.txt
Provides convenient functions like get, post, put, patch, and destroy for making HTTP requests with a concise syntax. These functions handle common configurations and response types, simplifying request creation compared to direct Fetch API instantiation. They support options for query parameters, request bodies, content types, and response kinds.
```javascript
import { get, post, put, patch, destroy } from '@rails/request.js'
// GET request returning JSON
async function fetchUsers() {
const response = await get('/api/users', {
query: { active: true },
responseKind: 'json'
})
if (response.ok) {
return await response.json
}
}
// POST request with automatic JSON stringification
async function createPost() {
const response = await post('/posts', {
body: {
title: 'New Post',
content: 'Post content here',
published: true
},
responseKind: 'json'
})
if (response.ok) {
const newPost = await response.json
console.log('Created post ID:', newPost.id)
return newPost
} else if (response.unauthenticated) {
console.error('Authentication required')
// User will be redirected to authenticationURL automatically
}
}
// PUT request to update resource
async function updateUser(userId, updates) {
const response = await put(`/users/${userId}`, {
body: updates,
contentType: 'application/json'
})
return response.ok
}
// PATCH request for partial updates
async function toggleUserStatus(userId) {
const response = await patch(`/users/${userId}/toggle_status`, {
body: { active: true },
responseKind: 'json'
})
return await response.json
}
// DELETE request (using destroy to avoid reserved keyword)
async function deletePost(postId) {
const response = await destroy(`/posts/${postId}`, {
responseKind: 'json'
})
if (response.ok) {
console.log('Post deleted successfully')
return true
}
return false
}
// Error handling pattern
async function robustRequest() {
try {
const response = await post('/api/endpoint', {
body: { data: 'value' },
responseKind: 'json'
})
if (response.ok) {
return await response.json
} else if (response.statusCode === 422) {
const errors = await response.json
console.error('Validation errors:', errors)
return { errors }
} else {
throw new Error(`Request failed: ${response.statusCode}`)
}
} catch (error) {
console.error('Network error:', error)
throw error
}
}
```
--------------------------------
### Implement Request Progress Bars with JavaScript
Source: https://context7.com/rails/request.js/llms.txt
This snippet demonstrates how to wrap HTTP requests with progress bar indicators using pure JavaScript. It utilizes `@rails/request.js` and `@hotwired/turbo` to show and hide a progress bar during request execution. Dependencies include `FetchRequest` from `@rails/request.js` and `navigator` from `@hotwired/turbo`. It provides functions for `get` and `post` requests that automatically manage the progress bar.
```javascript
import { FetchRequest } from "@rails/request.js"
import { navigator } from "@hotwired/turbo"
// Progress bar helper functions
function showProgressBar() {
const progressBar = navigator.delegate.adapter.progressBar
progressBar.setValue(0)
progressBar.show()
}
function hideProgressBar() {
const progressBar = navigator.delegate.adapter.progressBar
progressBar.setValue(1)
progressBar.hide()
}
// Wrap requests with progress indication
export function withProgress(requestPromise) {
showProgressBar()
return requestPromise
.then((response) => {
hideProgressBar()
return response
})
.catch((error) => {
hideProgressBar()
throw error
})
}
// Custom HTTP methods with progress bars
export function get(url, options) {
const request = new FetchRequest("get", url, options)
return withProgress(request.perform())
}
export function post(url, options) {
const request = new FetchRequest("post", url, options)
return withProgress(request.perform())
}
// Usage in application
import { get, post } from './request-with-progress'
async function loadData() {
// Progress bar shown automatically
const response = await get('/api/large-dataset', {
responseKind: 'json'
})
// Progress bar hidden after response
return await response.json
}
```
--------------------------------
### Register Bearer Token Authentication Interceptor
Source: https://context7.com/rails/request.js/llms.txt
Registers an interceptor to automatically add a Bearer token to outgoing requests. It fetches the token from secure storage and adds it to the 'Authorization' header. Subsequent requests made with 'get' or 'post' from '@rails/request.js' will include this token.
```javascript
import { RequestInterceptor, get, post } from '@rails/request.js'
// Register interceptor for Bearer token authentication
RequestInterceptor.register(async (request) => {
// Fetch token from secure storage
const token = await getAuthToken()
if (token) {
request.addHeader('Authorization', `Bearer ${token}`)
}
})
// All subsequent requests will include the Authorization header
async function authenticatedRequest() {
// Token is automatically added by interceptor
const response = await get('/api/protected-resource', {
responseKind: 'json'
})
return await response.json()
}
```
--------------------------------
### Basic FetchRequest Usage in JavaScript
Source: https://github.com/rails/request.js/blob/main/README.md
Demonstrates how to import and use the FetchRequest class to send a POST request to a Rails endpoint. It shows how to instantiate FetchRequest with method, URL, and options, perform the request, and handle the response.
```javascript
import { FetchRequest } from '@rails/request.js'
....
async myMethod () {
const request = new FetchRequest('post', 'localhost:3000/my_endpoint', { body: JSON.stringify({ name: 'Request.JS' }) })
const response = await request.perform()
if (response.ok) {
const body = await response.text
// Do whatever do you want with the response body
// You also are able to call `response.html` or `response.json`, be aware that if you call `response.json` and the response contentType isn't `application/json` there will be raised an error.
}
}
```
--------------------------------
### Setting up Turbo Integration in JavaScript
Source: https://github.com/rails/request.js/blob/main/README.md
Provides the necessary JavaScript code to integrate Rails Request.JS with Turbo. It shows how to import and assign the Turbo object to the window, enabling automatic processing of Turbo Stream responses.
```javascript
import { Turbo } from "@hotwired/turbo-rails"
window.Turbo = Turbo
```
--------------------------------
### Turbo Stream Integration
Source: https://context7.com/rails/request.js/llms.txt
This section explains how to integrate with Turbo Streams for real-time page updates, including setting up Turbo, making requests with `responseKind: 'turbo-stream'`, and handling different response scenarios.
```APIDOC
## POST /posts
### Description
Creates a new post and expects a Turbo Stream response for updating the UI.
### Method
POST
### Endpoint
/posts
### Parameters
#### Request Body
- **post** (object) - Required - Contains the title and content of the new post.
### Request Example
```json
{
"post": {
"title": "New Post",
"content": "Content here"
}
}
```
### Response
#### Success Response (200)
- **turbo-stream** - The response will be a Turbo Stream that automatically updates the page.
#### Response Example
```html