我试图在使用Vue.js和Dropzone的Rails 5.1应用程序中提交表单。在sendingEvent
期间,我在对象上使用JSON.stringify
,然后将其发送给控制器。但是,我不觉得这是正确的方法,因为我在控制器中使用强params时遇到了问题。
JS :
import Vue from 'vue/dist/vue.esm'
import VueResource from 'vue-resource'
import vue2Dropzone from 'vue2-dropzone'
Vue.use(VueResource)
document.addEventListener('DOMContentLoaded', () => {
if(document.getElementById('listing-multistep') !== null) {
Vue.http.headers.common['X-CSRF-Token'] = document.querySelector('input[name="authenticity_token"]').getAttribute('value');
var listingForm = document.getElementById('listing_form');
var listing = JSON.parse(listingForm.dataset.listing);
var locale = document.getElementsByTagName('html')[0].getAttribute('lang');
const myForm = new Vue({
el: '#listing-multistep',
components: {
vueDropzone: vue2Dropzone
},
data: function () {
return {
id: listing.id,
locale: locale,
slug: listing.slug,
activeStep: 0,
// More data
dropzoneOptions: {
url: `/${locale}/listings`,
method: 'post',
acceptedFiles: 'image/*',
uploadMultiple: true,
autoProcessQueue: false,
parallelUploads: 15,
maxFiles: 15,
addRemoveLinks: true,
thumbnailWidth: 150,
maxFilesize: 5,
dictDefaultMessage: "<i class='fa fa-cloud-upload'></i> Drop files here to upload (max. 15 files)",
headers: { 'X-CSRF-Token': Vue.http.headers.common['X-CSRF-Token'] }
}
}
},
methods: {
sendingEvent: function(file, xhr, formData) {
// This function gets called by Dropzone upon form submission.
var listingObj = this.setupListingObj()
formData.append('listing', JSON.stringify(listingObj))
},
listingRedirect: function(files, response) {
window.location = `/${this.locale}/listings/${response.slug}`
},
submitListing: function() {
var numFiles = this.$refs.listingDropzone.getAcceptedFiles().length
// If there are images to upload, use Dropzone
// Else submit the form normally.
if(numFiles > 0) {
this.$refs.listingDropzone.processQueue()
} else {
var listingObj = this.setupListingObj()
if(this.id === null) {
// POST if it's a new listing
this.$http.post(`/${this.locale}/listings`, {listing: listingObj}).then(
response => {
window.location = `/${this.locale}/listings/${response.body.slug}`
}, response => {
console.log(response)
})
} else {
// PUT if it's an existing listing
this.$http.put(`/${this.locale}/listings/${this.slug}`, {listing: listingObj}).then(
response => {
window.location = `/${this.locale}/listings/${response.body.slug}`
}, response => {
console.log(response)
})
}
}
},
setupListingObj: function() {
// do some processing...
var listingObj = {
id: this.id,
name: this.name,
// set more attributes
}
return listingObj
},
}
}
});
正如您所看到我在formData.append('listing', JSON.stringify(listingObj))
上使用sendingEvent
。
我的控制器:
class ListingsController < ApplicationController
def create
@listing = Listing.new JSON.parse(params[:listing])
@listing.owner = current_user
respond_to do |format|
if @listing.save
format.html { redirect_to listing_path(@listing), notice: 'Listing was created successfully!' }
format.json { render :show, status: :created, location: @listing }
else
format.html { render :new }
format.json { render json: @listing.errors, status: :unprocessable_entity }
end
end
end
private
def listing_params
params.require(:listing).permit(
:name,
:bedrooms,
:beds,
:bathrooms,
:price_cents,
:price_currency,
:property_type,
:city,
:state,
:address,
:lat,
:lng,
:description,
:amenities => []
)
end
end
它似乎在开发中工作,但是当我在RSpec中使用此代码运行测试时,我得到的错误如下:
Internal Server Error no implicit conversion of ActionController::Parameters into String
当我尝试交换@listing = Listing.new JSON.parse(listing_params)
时,它无法在开发中工作。
我有一种感觉,我没有正确发送表单数据。通过Javascript将数据发送到我的Rails控制器的正确方法是什么?是否需要进行调整然后发布?我怎样才能通过强对数来访问它?
提前致谢!
更新
这是我的规范:
RSpec.feature 'Listing owners can create new listings' do
let(:owner) { create(:user, :owner) }
before do
login_as owner
visit new_listing_path
end
scenario 'successfully', js: true do
fill_in 'Property name', with: 'Example property'
select 'Apartment', from: 'Property type'
fill_in 'Address', with: 'Somewhere'
click_button 'Next'
fill_in 'Property description', with: Faker::Lorem.paragraph(2)
click_button 'Create Listing'
expect(page).to have_content 'Listing was created successfully!'
end
end
我正在使用Chrome无头进行这些测试,以便解析表单上的Vue.js内容。在我的 rails_helper.rb 中,我有:
require 'spec_helper'
require 'rspec/rails'
require 'capybara/rails'
require 'capybara/rspec'
require 'pundit/rspec'
require 'selenium/webdriver'
RSpec.configure do |config|
# ...
Capybara.javascript_driver = :headless_chrome
end
我有 support / chrome_driver.rb 文件,其中包含以下内容:
Capybara.register_driver(:headless_chrome) do |app|
capabilities = Selenium::WebDriver::Remote::Capabilities.chrome(
chromeOptions: { args: %w[headless disable-gpu] }
)
Capybara::Selenium::Driver.new(
app,
browser: :chrome,
desired_capabilities: capabilities
)
end