Angular5对接Rails5+Shrine:如何通过tus-js-client传递匹配的name属性
Let's break down how to get your Angular 5 + Rails 5 + Shrine + Uppy/tus setup working correctly, focusing on aligning frontend params with Rails' strong parameters.
Key Background
The core issue here is that Rails expects nested parameters (like movie[title] or a top-level movie object containing all fields) to map to your model, and Shrine relies on a video_data parameter to attach the uploaded file. Since you're using Uppy's built-in submission instead of Rails forms, we need to explicitly shape the data sent to Rails.
Step 1: Frontend Uppy Configuration
You have two reliable approaches to structure your requests correctly:
Option A: Manual Request After Tus Upload
Use Uppy's complete hook to handle file upload success, then send structured movie data (including Shrine-generated video_data) to your /movies endpoint:
// Initialize Uppy with Tus plugin const uppy = Uppy.Core({ debug: true }) .use(Uppy.Tus, { endpoint: '/files', // Your Shrine tus endpoint retryDelays: [0, 3000, 5000, 10000], headers: { 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content } }); // Handle upload completion uppy.on('complete', (result) => { if (result.successful.length === 0) return; const uploadedFile = result.successful[0]; // Extract video_data from the uploaded file's metadata (adjust based on your Shrine setup) const videoData = uploadedFile.meta.video_data; // Gather form fields const movieData = { title: document.getElementById('movie-title').value, year: document.getElementById('movie-year').value, plot: document.getElementById('movie-plot').value, video_data: videoData }; // Send structured request to Rails fetch('/movies', { method: 'POST', headers: { 'Content-Type': 'application/json', 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content }, body: JSON.stringify({ movie: movieData }) }) .then(res => res.json()) .then(data => console.log('Movie created:', data)) .catch(err => console.error('Error:', err)); });
Option B: Use Uppy Form Plugin for Field Mapping
If you want Uppy to handle form field collection, set your HTML inputs to use Rails-friendly name attributes, then configure the Form plugin:
<form id="movie-upload-form"> <input type="text" id="title" name="movie[title]" required> <input type="number" id="year" name="movie[year]" required> <textarea id="plot" name="movie[plot]"></textarea> <div id="uppy-target"></div> </form>
const uppy = Uppy.Core() .use(Uppy.Form, { target: '#movie-upload-form', submitOnSuccess: false }) .use(Uppy.Tus, { endpoint: '/files', headers: { 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content } }); uppy.on('submit', (result) => { if (result.successful.length === 0) return; // Build FormData with Rails-compatible params const formData = new FormData(); const movieMeta = uppy.getState().meta; // Add form fields Object.keys(movieMeta).forEach(key => { if (key.startsWith('movie[')) formData.append(key, movieMeta[key]); }); // Add video_data from the uploaded file formData.append('movie[video_data]', result.successful[0].meta.video_data); // Submit to Rails fetch('/movies', { method: 'POST', body: formData, headers: { 'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]').content } }); });
Step 2: Rails Backend Adjustments
Update your movie_params to accept the video_data field (this is what Shrine uses to attach the uploaded file):
# app/controllers/movies_controller.rb def create movie = Movie.new(movie_params) if movie.save render json: movie, status: :created else render json: { errors: movie.errors }, status: :unprocessable_entity end end private def movie_params # Permit the fields you need, including video_data for Shrine params.require(:movie).permit(:title, :year, :plot, :video_data) end
Ensure your Sequel model is set up correctly with Shrine:
# app/models/movie.rb class Movie < Sequel::Model include VideoUploader::Attachment.new(:video) end
Step 3: Verify and Debug
- Check your Rails server logs to inspect incoming
Parameters:– this is critical for debugging. If you see flat params like{"title"=>"Test"}instead of nested{"movie"=>{"title"=>"Test"}}, adjust your frontend request structure. - Confirm your Shrine tus endpoint returns
video_dataafter a successful upload. Test this by directly uploading a file to/filesand checking the response. - Make sure the Rails CSRF token is included in all POST requests – missing this will trigger 422 errors.
内容的提问来源于stack exchange,提问作者user3799793

