I am trying to add a select box to the base of my create form that decides if an action runs from the controller...if that makes any sense?
Basically the application creates a project in FreeagentCentral whenever a new project is made:
def create
#company = Company.find(params[:kase][:company_id])
#kase = #company.kases.create!(params[:kase])
respond_to do |format|
params[:send_to_freeagent] ? #kase.create_freeagent_project(current_user)
#flash[:notice] = 'Case was successfully created.'
flash[:notice] = fading_flash_message("Case was successfully created.", 5)
format.html { redirect_to(#kase) }
format.xml { render :xml => #kase, :status => :created, :location => #kase }
end
end
and within my form I have:
<%= check_box_tag :send_to_freeagent, 1 %> Create project in Freeagent?
What I would like to happen, is if the select box is checked the project is sent to Freeagent. If not, the case just gets created locally as normal but without the Freeagent data being sent.
If I use the above code, I get an exception caught error:
SyntaxError in KasesController#new
controllers/kases_controller.rb:114: syntax error, unexpected '\n'
Any idea what I am doing wrong?
I'd use
def create
#company = Company.find(params[:kase][:company_id])
#kase = #company.kases.create!(params[:kase])
#kase.create_freeagent_project(current_user) if params[:send_to_freeagent].to_bool
respond_to do |format|
# ...
end
end
Related
I am running rails 3.2
I have created a nested form (requests > tags) with coffeescript handling the addition of new tags.
Everything works with the exception of the form posting a blank tag.name
I am trying to write a method to delete the blank field before the form posts. I realize this may be the wrong approach, but I am still a beginner:
requests_controller.rb
def create
#request = current_user.requests.build(params[:request])
#tag = Tag.new
if #tag.name.blank?
destroy_blank
end
respond_to do |format|
if #request.save
format.html { redirect_to(#request,
:notice => 'Request was successfully created.') }
format.json { render :json => #request,
:status => :created, :location => #request }
else
format.html { render :action => "new" }
format.json { render :json => #request.errors,
:status => :unprocessable_entity }
end
end
end
request.rb
def destroy_blank
blank = #tag.name
blank.delete
end
I hope that's clear. If not let me know and I will include more information.
If you can't stop blank tags from coming in, you can create a before_create filter in the model to skip saving blank tags. Leave the controller clean and simple.
Good luck!
I want to present users with separate pages/dialogs for editing their own information. However, the information is held in a single model (called User). Now I'm trying to find the best approach for handling the update calls from partials. My code currently:
def edit
render :layout=>!request.xhr?
end
def edit_password
render :layout=>!request.xhr?
end
def edit_extra
unless #user.extra
#user.build_extra
#user.extra.value = 2047
end
render :layout=>!request.xhr?
end
def update
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, :notice => 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render :action => "edit", :layout=>!request.xhr? }
end
end
end
The thing is, all forms in methods (edit, edit_password and edit_extra) call the update method. However, there are two problems:
If the data parsing isn't validated, user is presented with the "edit" form, which is incorrect.
I want to have a password confirmation on extra data. User shouldn't be able to edit that information unless they supply a correct password.
I would like to make more generalized solution than just duplicating the update -code. The largest problem is rendering correct layout (edit, edit_password) based on the current action.
For now, I solved the problem by creating separate edit_section parameter that will be handled in update.
def update
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to #user, :notice => (t :actionsuccesful) }
format.json { head :no_content }
else
action = if params[:edit_section] then "edit_" + params[:edit_section] else "edit" end
format.html { render :action => action, :layout=>!request.xhr? }
end
end
end
And in forms (edit_password, etc)
=form_for(#user, :remote => true) do |f|
= hidden_field_tag :edit_section, "password"
I'm trying to get my head around saving to multiple models from the one controller and it's probably really simple but I can't figure it out.
I have a User Model that has many loanitems and the loanitems belong to the user associations set up.
In my loanitems controller I want each loanitem create action to update a the user.points
So at the moment I have the following code that doesn't throw any errors but doesn't update the user model either.
def create
#loanitem = current_user.loanitems.build(params[:loanitem])
respond_to do |format|
if #loanitem.save
#loanitem.user.points = #loanitem.user.points + 50
#loanitem.user.save
format.html {redirect_to root_path, :flash => {:success => "Loan Item created" } }
format.xml{render xml: root_path}
else
format.html {render 'pages/home' }
format.xml {render xml: 'pages/home'}
end
end
end
I'm also trying the following variation on a theme
def create
#loanitem = current_user.loanitems.build(params[:loanitem])
respond_to do |format|
if #loanitem.save
current_user.points = current_user.points + 50
current_user.save
format.html {redirect_to root_path, :flash => {:success => "Loan Item created" } }
format.xml{render xml: root_path}
else
format.html {render 'pages/home' }
format.xml {render xml: 'pages/home'}
end
end
end
But should I be sending some message instead to the userupdate controller instead? That currently looks like this ...
def update
#user = User.find(params[:id])
if
#user.update_attributes(params[:user])
redirect_to #user, :flash => { :success => "Profile has been updated!"}
else
#title = "Edit Profile"
render 'edit'
end
end
Or I have heard that the business logic really should all be contained in the model so maybe the method should be written in User.rb and then called by the Loanitems controllers create method?
I know it's a real rookie question but any advice would be really welcome.
It sounds like you need to use a Transaction, so you can modify multiple items as a single atomic unit:
def create
respond_to do |format|
User.transaction do
begin
#loanitem = current_user.loanitems.create!(params[:loanitem]) # raises exception if it can't create
#loanitem.user.update_attributes!(:points => #loanitem.user.points + 50) # raises exception if it can't update
format.html {redirect_to root_path, :flash => {:success => "Loan Item created" } }
format.xml{render xml: root_path}
rescue ActiveRecord::RecordInvalid
format.html {render 'pages/home' }
format.xml {render xml: 'pages/home'}
raise ActiveRecord::Rollback
end
end
end
end
This allows you to have a simple happy-path where multiple objects are updated/created and roll-back all changes so far if anything goes wrong and render your error handling logic. The objects will have the validation messages you can display to the user.
I've got an problem with my update action for a nested resource.
In my app, my orders have many invoices.
Creating a new invoice, I correctly end up with the following url:
/orders/11/invoices/new
And when I edit the invoice, again, it's all correct:
/orders/11/invoices/3/edit
This works fine when the save is a success, however if the validation fails, it routes back to:
/invoices/3
I have the following in my invoices controller:
def update
# #order = Order.find(params[:order_id])
# #invoice = #order.invoices.find(params[:id])
#invoice = Invoice.find(params[:id])
respond_to do |format|
if #invoice.update_attributes(params[:invoice])
format.html { redirect_to(order_invoice_path(#invoice.order, #invoice), :notice => 'Invoice was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #invoice.errors, :status => :unprocessable_entity }
end
end
end
def edit
#invoice = Invoice.find(params[:id])
3.times { #invoice.invoice_items.build }
end
I'm assuming I need to edit the #invoice.errors part but I don't know what to change it to?
Any help appreciated. Jx
When updating failed, you use "render" (comparing with the "redirect_to" in the succeeding path), this brings you to invoice editing path by default. You can use "redirect_to" here to keep the URI path you want, but need remembering to preserve the models' states so your users don't need to fill the entire form all over again.
A detail instruction can be found here: How to make a render :edit call show the /edit in the address bar
Yan
in your form you should add your order, like this:
<%= form_for [#order, #invoice] ... do |f| %>
...
<% end %>
And then uncomment this two lines
# #order = Order.find(params[:order_id])
# #invoice = #order.invoices.find(params[:id])
so your form will send its request to POST /orders/XX/invoices/XX
I have the following code in my controller:
# GET /kases/1/edit
def edit
#kase = Kase.find(params[:id])
respond_to do |format|
format.html { render :layout => 'kaseshow'} # show.html.erb
format.xml { render :xml => #kase }
format.pdf { render :layout => false }
end
end
# POST /kases
# POST /kases.xml
def create
#company = Company.find(params[:kase][:company_id])
#kase = #company.kases.new(params[:kase])
if #kase.save
UserMailer.deliver_makeakase("xxxxxx#xxxxxxxx.com", "Highrise", #kase) if params[:sendtohighrise]
UserMailer.deliver_makeakaseteam("xxxxxxxx#xxxxxxx.co.uk", "Highrise", #kase) if params[:notify_team_of_creation]
#kase.create_freeagent_project(current_user) if params[:send_to_freeagent]
redirect_to(#kase)
#flash[:notice] = 'Case was successfully created.'
flash[:notice] = fading_flash_message("Case was successfully created.", 5)
else
render :new
end
end
I am trying to make it so if the user edits a case and then selects the Send to Freeagent tickbox:
#kase.create_freeagent_project(current_user) if params[:send_to_freeagent]
then the case is resent to Freeagent (online accounting software). I'm not worried about dealing with duplicates because if the case already exists in Freeagent then the user won't need to resend it.
Is this possible?
Where is your 'update' method? The edit is only called when you are loading the data and rendering the page the user will see to edit the record. When save/update/submit is clicked on that page, it should be calling the 'update' method in the controller. So, you should be able to put that same line into the 'update' method in the true condition of the if block that looks something like this:
if #kase.update_attributes(params[:kase])
#your code would go here
#kase.create_freeagent_project(current_user) if params[:send_to_freeagent]
#the rest of the code would go here
end
It is, you could create checkbox/radio/hidden field in your edit form.
If you want to create some models for the Kase, you could as well look at accepts_nested_attributes