Rails: Generic form actions, cancel link losing `:back` on validation failure - ruby-on-rails

I am trying to create a generic set of Submit, Cancel, and Destroy actions for forms. At this point, it appears that everything is working, except that I lose :back functionality then a form reloads due to validation errors. Is there a way to catch the fact that validation has failed, and in that case, keep the request.env['HTTP_REFERER'] or :back value the same without having to edit every controller?
= simple_form_for #announcement do |f|
= f.error_notification
= f.input :message
= f.input :starts_at
= f.input :ends_at
#submit
= f.button :submit
= "or "
= link_to("cancel", url_for(:back))
.right
- if !f.object.new_record?
- resource = (f.object.class.name).downcase
= link_to "destroy", url_for(:action => 'destroy'), :confirm => "Are you sure that you want to delete this #{resource}?", :method => :delete
.clear
.non_input
#post_back_msg
#indicator.inline
= image_tag "indicator.gif"
.inline
= "Please wait..."
.non_input

How about something like a helper method with something like this?
#previous = #previous.blank? ? request.env['HTTP_REFERRER'] : #previous
Then the Cancel button is just:
link_to('Cancel', #previous)

Does this work?
link_to "Cancel", #model.errors.any? ? request.env['HTTP_REFERRER'] : :back

Related

Rails form on a single page

I am trying to get each candidate belonging to a position have its own page. How do I implement this?
= form_for #vote do |f|
- Position.includes(:candidates).order(:name).each do |position|
= position.name
- position.candidates.each do |candidate|
= image_tag(candidate.image, :size => '50x50') if candidate.image.attached?
= candidate.name
= candidate.info
= f.check_box :c_votes
= f.submit "Submit"
When I use this code it creates a submit button for each candidate on the same page.

Proper syntax for controller action with slim

Rails 3.2
I have a view views/tickets/show.html.slim with a number of sections. I want to have different controllers for each section, and have actions like New Save Edit
So in my views/tickets/show.html.slim, I have:
- #customer_info = customer_info #ticket
h4.form-header Customer Information
.form-section.attachments
- if #customer_info.nil?
= render partial: 'tickets/sections/customer_info', locals: {ticket: #ticket }
In my view, I have:
= form_for CustomerInfo.new do |f|
- f.hidden_field :ticket_id, :value => ticket.id
.form-horizontal-column.customer-info
.form-group
= f.label :first
= f.text_field :first, maxlength: 50
.form-group
= f.label :last
= f.text_field :last, maxlength: 50
- logger.info("Marker 1")
.actions = link_to "Save", :controller => :customer_infos, :action => :create
- logger.info("Marker 2")
.clear
When I run the application in test mode, and I select a ticket, I get the following response:
Incomplete response received from application
In my test.log file, I have:
CustomerInfo Load (0.1ms)[0m SELECT customer_infos``.* FROMcustomer_infosWHEREcustomer_infos.ticket_id` = '1466026127' LIMIT 1
Marker 1
Rendered tickets/sections/_customer_info.html.slim (11.6ms)
Rendered admin/tickets/show.html.slim within layouts/application (563.0ms)
There is no Marker 2
If I replace:
.actions = link_to "Save", :controller => :customer_infos, :action => :create
With:
.actions = f.submit 'Save'
Then the form renders fine.
Any idea why this is not working?
Attempted fix:
In my tickets/section/_customer_info.html.slim, I did:
.actions = link_to "Save", create_customer_info_path, method: :post
In my routes.rb, I have:
post '/customer_infos/create' => 'customer_infos#create', as: 'create_customer_info'
I am now getting the following error message:
undefined method `customer_infos_path' for #<#<Class:0x00000008bb54d8>:0x00000009df3c30>
Where is customer_infos_path coming from?
If I do rake routes, I get:
create_customer_info POST /customer_infos/create(.:format) customer_infos#create
According to the Rails docs, using the controller option is frowned upon. You should set up your route with a name, like this:
post '/customers/create' => 'customer_infos#create', as: 'create_customer'
Then your view should look something like this:
.actions
= link_to "Save", create_customer_path, method: :post
Hope this helps!

Validate presence of attributes on edit page

This is a complicated one so I will try to explain as best as I can. I have an attachment model and I am using carrierwave_direct as the gem. Carrierwave_direct requires uploading on one page and then the attributes on another page. The other page it needs to redirect you to is the edit page, however the attributes on the edit page I cannot validate through the model, unless I want the upload to fail(because it won't create an id with validations meant for another page.). I think what I am saying is how would I validate that model attributes have a presence only on the edit page and if the user exits the page without filling in the form, it deletes the model instance. I want it to do this because for my model to work they need it to create the model instance on upload. See my code in the controller below
def edit
#attachment = Attachment.find(params[:id])
end
def report_uploader
#uploader = Attachment.new.delivery
#uploader.success_action_redirect = uploaded_attachments_url
#uploader
end
helper_method :report_uploader
def after_upload
#attachment = Attachment.new(recruiter_id: current_user.id, uploader_name: current_user.first_name + " " + current_user.last_name)
#recruiter = current_user
#attachment.url = #attachment.delivery.direct_fog_url + params[:key]
#attachment.key = params[:key]
#attachment.filename = File.basename(#attachment.key)
#attachment.save
redirect_to edit_attachment_path(id: #attachment.id, :anchor => 'reports')
end
attachment modal
.head
%h2 Add Attachment
.close
%a{:href=>"#",:rel=>"modal:close"} ❎
.content
= direct_upload_form_for report_uploader , :html => { :class => "standard" } do |f|
.fieldgroup.upload
.field
.upload
= link_to "#", class: "btn primary" do
= image_tag 'loader-white.gif', alt: 'Loading', class: 'loading'
Upload Attachment
= f.file_field :delivery, class: 'file_upload', id: 'upload_attachment'
edit page(User is redirected here)
.content
%h2 Add Some Additional Stuff to your Attachment!
= form_for #attachment, html: {class: "standard manage-job"} do |f|
.fieldgroup.upload
.field
Your Attachment Title
%br
%a{href: attachment_path(id: #attachment.id), target: '_blank' }
= #attachment.filename
.field
%select{name: "attachment[attachment_type]"}
%option{value: ""} Select Attachment Type
%option{value: "Type A"} Type A
%option{value: "Type B"} Type B
%option{value: "Type C"} Type C
.field
Description of your Attachment
= f.text_area :description
.actions
= f.submit "Submit Report", class: "btn primary"
= link_to 'Cancel', attachments_path

get and post method in controller. Ruby on Rails

I trying rewrite some data in model. Change_settings is GET-method, update_settings is POST. After click SUBMIT happens nothing. Data not change. Help me, please( what's wrong?
controller
def change_settings
#vacation_days = current_company.vacation_days
#illnes_days = current_company.illnes_days
end
def update_settings
current_company.update_attribute(:vacation_days, :illnes_days)
current_company.save
redirect_to account_company_path, notice: t('company.settings_changed')
end
change_settings view
.company_settings
= form_tag update_settings_company_path do
= field_set_tag do
= label_tag 'vacation_days'
= text_field_tag :vacation_days
= label_tag 'illnes_days'
= text_field_tag :illnes_days
%br
= submit_tag t('common.save'), class: 'btn'
= link_to t('common.back'), account_company_path, class: 'btn'
routes
resource :company, only: :all do
get :account
get :change_settings
post :update_settings
end
replace:
current_company.update_attribute(:vacation_days, :illnes_days)
current_company.save
with:
current_company.update_attributes(vacation_days: params[:vacation_days], illnes_days: params[:illnes_days] )
Basically you were not taken data sent from client into account

Rails form params changing in controller

I have a form:
<%= form_for(:report_main, :url => {:action => 'exporttoxiccreate'}) do |f| %>
<%= collection_select(:waste, :code, Waste.find_all_by_istoxic(false), :id, :code, :include_blank => '') %>
<%= f.check_box(:q_pripadnost) %>
<%= f.text_field(:amount) %>
<% end %>
and this code in controller:
def exporttoxiccreate
#report = ReportMain.new
#reportexport = ReportExport.new
#reportparam = params[:report_main]
#report.waste_id = #reportparam.waste.code
#report.amount = #reportparam.amount
if #report.save
#reportexport.report_main_id = #report.id
else
redirect_to(:action => 'exporttoxicnew')
end
#reportexport.q_pripadnost = #reportparam.q_pripadnost
if #reportexport.save
redirect_to(:action => 'show', :id => #reportexport.id)
else
redirect_to(:action => 'exporttoxicnew')
end
end
I want to save in two tables, in two objects data from this form, and I need to separate params to manipulate with. I tried with this:
#reportexport.q_pripadnost = #reportparam.q_pripadnost
I want to set q_pripadnost field in #reportexport with some value from param.
Where I make mistake?
When you get params from a form in Rails, it comes in the form of a hash. For example:
params[:report_main][:waste]
params[:report_main][:amount]
So when you call #reportparam = params[:report_main], you are setting #reportparam to a hash, but then you are trying to use it later like an object. For example, instead of #reportparam.q_pripadnost, use #reportparam[:q_pripadnost].
You can take a closer look at your variable by temporarily changing your action to show a text version of the variable, for example:
def exporttoxiccreate
#reportparam = params[:report_main]
render :text => #reportparam.to_yaml
end

Resources