How do I get redirect to view after create action using Vue.js
Out of interest, have a weird issue. Trying to do a redirect after create. The record is being created just fine, but get a 500 error on the redirect? Using an ajax call using Vue-resource. Below is the code. (gist for better readability : https://gist.github.com/tabishiqbal/6c3839e53b5c5d34f0cbcc98185bb326)
CREATE METHOD IN CONTROLLER
def create
@proposal = @project.proposals.create(proposal_params)
authorize @proposal
respond_to do |format|
if @proposal.save!
format.html { redirect_to project_proposal_path(@proposal.project, @proposal), notice: "Proposal successfully created and submitted to the client" }
format.json { render :show, status: :created, location: @proposal }
@project.update_attribute(:status_id, set_quote_ready)
# As there is a new final, all previous versions are no longer current
@project.proposals.where.not(id: @proposal.id).update_all(current: false)
# Set this new final version as the current version
if @project.proposals.all_final.count > 1
@user.notify_user("#{@project.supplier.display_name} has updated their proposal. Check it out!", @project.id)
@project.supplier.notify_business("Your revised proposal has been submitted to the client for approval", @project.id)
else
@user.notify_user("#{@project.supplier.display_name} has submitted a proposal for your project. Accept it to start the project", @project.id)
@project.supplier.notify_business("Your proposal has been submitted to the client for approval", @project.id)
end
#UserMailer.new_proposal(@project.user).deliver_now
else
format.html { render :new, notice: "Proposal could not be saved" }
format.json { render json: @proposal.errors, status: :unprocessable_entity }
end
end
end
SAVE METHOD IN VUE
saveProposal: function(final) {
this.$validator.validateAll()
if (!this.errors.any()) {
this.saving = true
if (final == true ) {
this.proposal.final = true
} else {
this.proposal.final = false
}
for (var i = 0; i < proposal.milestones_attributes.length; i ++) {
var ms = proposal.milestones_attributes[i]
ms.dependencies_attributes = ms.dependencies
console.log(ms)
}
this.$http.post('/projects/' + this.proposal.project_id + '/proposals', {
proposal: proposal
})
.then(function (response) {
console.log('Saved successfully')
Turbolinks.visit('/projects/' + this.project.id + '/proposals/${response.body.id}')
})
.catch(error => {
console.log('Error saving proposal. Please correct the errors')
this.saving = false
});
** VIEW**
<%= content_tag :div,
id: "proposal-form",
data: {
project: @project.to_json(include: [:industry, :addons, :features, :budget, :type]),
proposal: @proposal.to_json(except: [:created_at, :updated_at]),
sections_attributes: @proposal.sections.to_json(except: [:proposal_id, :created_at, :updated_at]),
cost_items_attributes: @proposal.cost_items.to_json(except: [:proposal_id, :created_at, :updated_at]),
milestones_attributes: @proposal.milestones.to_json(except: [:proposal_id, :created_at, :updated_at], include: (:dependencies)),
feedback: @feedback.to_json
} do %>
<% end %>
PROPOSAL PARAMS
def proposal_params
params
.require(:proposal)
.permit(
:project_id,
:supplier_id,
:version,
:final,
:accepted,
:accepted_at,
:current,
billing_phases: [],
sections_attributes: [
:id,
:title,
:body
],
cost_items_attributes: [
:id,
:name,
:category,
:timing,
:price,
:quantity,
:taxable,
:tax,
:gross,
:net
],
milestones_attributes: [
:id,
:name,
:due_date,
:done,
dependencies_attributes: [
:id,
:name,
:due_date,
:done
]
]
)
.merge(
project_id: @project.id,
supplier_id: @project.supplier_id,
user_id: @project.user.id,
version: @version,
current: true
)
end
Chris:
what is your json look like
it is trying to do a proposal_url
but you don’t have a route for it?
Stephen
Hey @excid3 I’m doing a standard rails show view (not Json’d), but in terms of the JSON parsing, does this help?
PROPOSAL JSON
var project = JSON.parse(element.dataset.project)
var proposal = JSON.parse(element.dataset.proposal)
var sectionsAttributes = JSON.parse(element.dataset.sectionsAttributes)
var costItemsAttributes = JSON.parse(element.dataset.costItemsAttributes)
var milestonesAttributes = JSON.parse(element.dataset.milestonesAttributes)
var feedback = JSON.parse(element.dataset.feedback)
proposal.sections_attributes = sectionsAttributes
proposal.cost_items_attributes = costItemsAttributes
proposal.milestones_attributes = milestonesAttributes
Chris
you’re submitting the form with Vue-resource / axios
and it wants JSON back
you should see the request in rails say “as JSON”
right?
Stephen
wait a sec, are you referring to this:
format.json { render :show, status: :created, location: @proposal }
in the proposal create action?
Chris
you should do
format.json { render json: @proposal }
think of it this way
Javascript submits the form to Rails
JS tells it that it wasnt JSON in return
so Rails says okay cool, and calls the format.json block
it needs to render JSON to send back so the Javascript can parse it
and then the JS can redirect using Turbolinks.visit()
you have to include a url of some sort in the JSON back so it can know where to go
one simple thing is to do like
format.json { render json: @proposal, location: @proposal }
(edited)
the location will set a url in the HTTP location header you can use to redirect
and still give you the json data of the proposal
but your error from rails said there was no resources :proposals
in your routes
so it can’t make that url
you’ll have to fix that or change the url
Stephen
Ahhh, ok cool. Can you do nested resources with the JSON response? So at the moment, I wanted to redirect to something like /projects/121/proposals/24
Or do I need to create an unnested route for the proposal show action?
Chris
just pass the url into location
format.json { render json: @proposal, location: [@project, @proposal] }
will probably work too
Chris
I haven’t actually used the location header with vue-resource so you may have to access it some different way
or you can put it into the json
nevermind, looks easy: Turbolinks.visit(response.headers.get('Location'));
Stephen
Omg, that worked!
Thats brilliant.
Chris you're awesome. I love you man. (his real words / feelings)