Rails 3.1 pass data through a post - ruby-on-rails

In my application, I've a 'warehouse' model that own several fields such as id,name,description, etc, and a boolean field called 'done'.
In my view, I want to insert a button or link field,which, when clicked, should set (through HTTP POST method) warehouse.done = true
How can I do this?
Notes: User cannot input warehouse.done field so I suppose to pass it to application as hidden field

Use link to with remote option.
<%= link_to "Vote", {:controller=>"your_controller_name", :action => 'vote',:id=>#warehouse.id, :vote=>true}, :remote=> true, :method => :put %>
In your controller
def vote
#warehouse = Warehouse.find(params[:id])
#warehouse.update_attribute(:vote, params[:vote])
respond_to do |format|
format.js
end
end
In your routes file
resources :your_controller_name do
collection do
put 'vote'
end
end
In your voting view page add new DIV to display flash notice.
<div id="flash_notice" style="display: none;"></div>
Create new RJS template "vote.js.erb" with following code.
$("#flash_notice").html("You have voted successfully");
$("#flash_notice").show("slow");
Let me know if you have any problem.

I made a couple of assumptions on the views, controller.
html
DONE
<input id="warehouse-id" type="hidden" value="24">
js
$(document).ready(function() {
$('#set-warehouse-done').click(function() {
$.ajax({
url: '/warehouse/' + $('#warehouse-id').attr('value');
type: 'POST'
data: done: true
});
});
}
warehouse_controller.rb
def update
#warehouse = Warehouse.find(params[:id])
if params[:done]
if #warehouse.update_attributes(:done, params[:done])
flash[:notice] = 'Warehouse updated successfully'
else
flash[:error] = 'Could not update warehouse'

Related

ActionController::InvalidAuthenticityToken on delete form Rails 4

I have a problem with Rails 4 and deleting multiple items in a database.
I am working on creating an email inbox and I would like to move an item into the "trash folder" and after that I want to redirect the user to the trash page, where he can delete the item from the database.
My code:
routes.rb
namespace :admin do
resources :inboxes do
collection do
match 'destroy_multiple' => 'inboxes#destroy_multiple', via: ['post','delete']
get 'sent'
get 'trash'
end
end
end
controller :
def destroy_multiple
if params[:action] == 'trash'
#del = Inbox.where(:id => params[:delete]).destroy_all
else
#del = Inbox.where(:id => params[:delete]).update_all(:folder =>'trash')
end
redirect_to admin_inboxes_path
end
And finally, my form (slim) :
= form_tag destroy_multiple_admin_inboxes_path, method: :delete, class: "multiple_delete" do
input type="hidden" name="action" value = controller.action_name
- #inboxes.each do |msg|
- #username = msg.email.gsub(/([^.]+)#.+/, '\1').gsub(/[^0-9A-Za-z]/, ' ').split.map(&:capitalize).join(' ')
tr class=(msg.read == 1 ? nil : 'unread')
td.inbox-small-cells
label.checkbox-custom.check-success
= check_box_tag "delete[]", msg.id, false, class: "for_del", id: "delete_#{msg.id}"
label for="delete_#{msg.id}"
td.inbox-small-cells
i.fa.fa-star.inbox-started
td
a.avatar href="/fr/admin/inboxes/#{msg.id}"
span.bg-primary =#username[0]
td.view-message.dont-show = #username
td.view-message = msg.subject
td.view-message.inbox-small-cells
td.view-message.text-right = msg.created_at.strftime("%d/%m")
I can with this code successfully move mail to the "trash", but I cannot delete them from the database.
Thank you!
You need to add the authenticity_token to your form. Try:
form_tag destroy_multiple_admin_inboxes_path, method: :delete, class: "multiple_delete", authenticity_token: true do
If you're working with a specific active record object, use form_for instead of form_tag, and the csrf field will automatically be built into the form by rails. However, this is a good time to be using form_tag.
The alternative solution is to change the config config.action_view.embed_authenticity_token_in_remote_forms to false, but this will make your site less secure, and it's better to just add authenticity_token: true to your form_tag.
Here is the documentation on form_tag

Render object attributes on the same site with click

There's this button / link in my web app. It's a button for a pizza - margherita with price, ingredients, and category, all already loaded to the db. Clicking this button loads the item's id to params, which is then used to find the object.
I want the click to launch the following chain of events:
Load the id
Find the object by id
Instantly render the object and its attributes in adjacent div on the same site.
Is this possible without JavaScript, just Ruby on Rails?
I am stuck at point 3. I have an idea, but incomplete. Please, give me a hint.
PS. My idea is to render views for index and show in separate divs next to one another.
#NickM, I added your code and it's throwing ActionController::UnknownFormat error, pointing at respond_to do |format| in show_pizza method.
Here's my pizzas/index.html.haml:
%h1= t :all_pizzas
- #pizzas.each do |pizza|
= render pizza
.orders
%h1 Orders
And pizzas/_pizza.html.haml:
%tr
= link_to pizza.name, show_a_pizza_path(pizza.id), :method => :post
%br/
I am getting this error upon clicking the link in _pizza.html.erb. My show_pizza.js is now:
pizza_div = $("#orders");
pizza_div.html( "<%= j render( :partial => 'pizzas/pizza', :locals => { :pizza => #pizza } ) %>" );
What am I missing? Sorry, I don't know js.
The short answer is no. When the link is clicked you will need to either render another page or handle the data returned by the controller with Javascript. The best option would be to set up an action that responds with JSON and parse what you get back on the front end.
Even after your P.S. you will have to handle the response from the server with Javascript, unless you are okay with rendering a new page. You need to post some code, preferably routes and controller action. This would also work:
<%= link_to("Show Pizza", show_a_pizza_path(#pizza.id), :method => :post, :data => {:remote => true}) %>
routes.rb
post 'show_pizza/:id' => "pizzas#show_pizza", :as => :show_a_pizza
pizzas_controller.rb
def show_pizza
#pizza = Pizza.find(params[:id])
respond_to do |format|
format.js
end
end
views/pizzas/show_pizza.js
pizza_div = $("#the_name_of_your_div");
pizza_div.html( "<%= j render( :partial => 'pizzas/pizza', :locals => { :pizza => #pizza } ) %>" );
and then put the pizza markup in /views/pizzas/_pizza.html.erb

rails 3.2 with ajax

Guys I have the following action on my controller to send emails to my users.
def email_all_users
User.all.each do |u|
if !u.information.nil?
if !u.information.business
UserMailer.candidate_email(u).deliver
else
UserMailer.business_email(u).deliver
end
else
UserMailer.no_info_email(u).deliver
end
end
redirect_to "/users/#{current_user.id}", :flash => { :success => "Los correos fueron enviados" }
end
And here is the link in my view
<%= link_to "Enviar Correos".html_safe, {:controller => "users", :action => "email_all_users"}, :method => "get", :id => "email_users", :html => {:style => "color:#FAA732;" }, :remote => true %>
<span id="loading" style="color:rgb(41, 160, 41);display:none;"><i class="icon-spinner icon-spin"></i> Enviando</span>
<span id="send" style="color:rgb(41, 160, 41);display:none;"><i class="icon-ok-circle"></i> Enviado!</span>
I create this file email_all_users.js.erb with this content
$('#email_users').hide();
$('#email_users').ajaxStart(function() {
$('#loading').show();
});
$('#email_users').ajaxComplete(function() {
$('#loading')..hide();
$('#send')..show();
});
As you can see after click in the link I want hide the link and show and image that I have in my loading span (loading is the id), then when the action finish I want to hide the loading and show my send span (send is the id of the span).
What I'm doing wrong because when I click the app send the emails, but does not hide the link and don't show the loading and the send.
Thanks in advance for your help
SOLUTION
I move my email_all_users.js.erb to my assets folder and I changed it like this:
$(document).ajaxStart(function() {
$('#email_users').hide();
$('#loading').show();
});
$(document).ajaxComplete(function() {
$('#loading').hide();
$('#send').show();
});
Problem solve.
Thanks anyway.
Those ajax calls need to go into a regular js file, not as a response to the action. When this code is getting called the ajax reques has already completed.

What is the Rails convention for sending form data to a URL dependent on form value?

I would like a form submitted at the url
/index/fruit
to submit the form data to
/index/:identifier
where :identifier is determined by a value of the form
What is the rails convention in this instance?
Is there a way to achieve this without a controller level redirect or javascript-updating the submit URL?
routes.rb
match 'smasher(/:action(/:id))', :controller => "customcontroller", :as => :smasher, :defaults => { :action => :index, :id => :fruit }
index.html.erb
<%= semantic_form_for :d, :url => smasher_path, :html => { :method => :get } do |f| %>
... form data ...
<%= f.input :identifier, :as => :hidden %>
<% end %>
My current implementation is similar to this answer
There's isn't really a "convention" for this, but rather one of those things where there's more than one way to do it.
One way that you could do it is still send the form to one and only one action within the controller, but then delegate in the controller which action to go to, like this:
def smasher
if params[:identifier] == 'this'
smash_this!
else
smash_that!
end
end
def smash_this!
# code goes here
end
def smash_that!
# code goes here
end
Heres the javascript version (though technically its all on an erb html template), if you're feeling up to it.
<%= f.input :identifier, :as => :hidden, :onchange => "$(this).setAction()" %>
<script>
// While you can this script block here within your erb template
// but best practice says you should have it included somehow within `<head></head>`
$(function() {
//create a method on the Jquery Object to adjust the action of the form
$.fn.setAction = function() {
var form = $(this).parents('form').first();
var action = form.attr('action')
form.attr('action', action.substr( 0, action.lastIndexOf('/')+1 ) + $(this).val());
}
});
</script>
Heres the pure javascript version:
$(function() {
//create a method on the Jquery Object to adjust the action of the form
$.fn.setAction = function() {
var form = $(this).parents('form').first();
var action = form.attr('action')
form.attr('action', action.substr( 0, action.lastIndexOf('/')+1 ) + $(this).val());
}
//we gotta bind the onchange here
$('input[name="identifier"]').change($.fn.setAction);
});

Ruby on Rails and how to render partial using json and jquery

Ruby on Rails newbie whose confused and frustrated :) I've spent over a day on this and think I've probably just confused myself.
Basically, I'm trying to render a partial in a view. Here's what I have specifically:
A form with 2 basic fields: Category and SubCategory. SubCategory changes depending on what the user selected in Category. I'm using "JQuery" with the assets pipeline enabled. This part works:
contact_infos.js.coffee
jQuery(document).ready(->
$("select#contact_info_category_id").change(->
id_value_string = $(#).val()
if id_value_string == ""
# if the id is empty remove all the sub_selection options from being selectable and do not do any ajax
$("select#contact_info_subcategory_id option").remove()
row = "" + "" + ""
$(row).appendTo("select#contact_info_subcategory_id")
else
# Send the request and update sub category dropdown
tmp = '/subcategories/for_categoryid/' + id_value_string + '.json'
$.ajax(
type: 'GET',
dataType: 'json',
url: tmp,
timeout: 2000,
error: (XMLHttpRequest, errorTextStatus, error) -> alert "Failed to submit : " + errorTextStatus + " ;" + error,
success: (data) ->
# Clear all options from sub category select
$("select#contact_info_subcategory_id option").remove()
# put in a empty default line
row = "" + "" + ""
$(row).appendTo("select#contact_info_subcategory_id")
# Fill sub category select
$.each(data, (i, j) ->
row = "" + j.name + ""
$(row).appendTo("select#contact_info_subcategory_id")
)
)
)
)
It generates a json response correctly.
When the form loads, in addition to Category and SubCategory, I also have 2 text fields - previous_value and current_value; however, if
SubCategory == "Full"
then I hide previous_value and current_value and need to insert a partial with new fields.
I'm having no problem hiding previous_value and current_value fields with JQuery works and looks like this (this is inserted into the code above):
$("select#contact_info_subcategory_id").change(->
id_text_string = $("#contact_info_subcategory_id option:selected").text()
if id_text_string == "Full"
$('#contact_info_previous_value_id').hide()
$('#contact_info_current_value_id').hide()
else
$('#contact_info_previous_value_id').show()
$('#contact_info_current_value_id').show()
)
I created a div called "test" in my form where I want to insert the new fields if SubCategory is "Full" and of course, inserting this line into the contact_infos.js.coffee doesn't work:
$('#test').html('<%= escape_javascript render("contact_infos/_full_name_info") %>')
as all I get on the page is the string "<%= escape_javascript render("contact_infos/_full_name_info") %>"
I've tried the following but can't get any to work:
1. creating a new.json.erb file with the following code:
<% self.formats = ["html"] %>
test = {
"html":"<%= raw escape_javascript(render :partial => 'contact_infos/full_name_info',
:content_type => 'text/html')}
%>"
}
This json file never triggered. My controller has this line:
format.json { render json: #contact_info }
Is this the best way to do this? If yes, what can I try next?
2. I saw a posting yesterday (I can't find it now - was on another computer) about creating a javascript variable (I called it fullnamefield) in the application.html.erb layout file as well as adding the js variable to the new.html.erb view, which I did. I also added this line to the contacts_infos.js.coffee:
('#test').html(fullnamefield)
and it worked!! EXCEPT that then when I went to any other area of the site, I got an error.
3. As a workaround, I thought about trying to change the json that my jquery produces to a js and then trying to trigger the new.js.erb. I ran into trouble trying to convert the ajax call. I could create "json" and also "text" dataTypes but not script (not sure why).
So... any ideas/help? I've really been searching and I'm frustrated enough that I'm considering just creating all the fields and hidings/showing them as needed from JQuery, which would be so simple to implement but is just wrong.
UPDATE: Attempt 4 (or is it 40?):
What you wrote got me thinking... I think I'm close but not there yet.
In my _form.html.erb, I added to the Subcategory field data-remote, data-url and data-type:
<div class="field">
<%= f.label :category_id %>
<br/>
<%= collection_select(:contact_info, :category_id, Category.all, :id, :name, options ={:prompt => "--Select a Category--"}) %>
</div>
<div class="field">
<%= f.label :subcategory_id %>
<br/>
<%= collection_select(:contact_info, :subcategory_id, Subcategory.find_all_by_category_id(#contact_info.category_id), :id, :name, options ={:prompt => "--Select a SubCategory"}, "data-remote" => true, "data-url" => "/contact_infos/get_full_fields", "data-type" => :json ) %>
</div>
Then in the contact_infos_controller.rb I added:
def get_full_fields
#full_name = FullName.new
respond_to do |format|
format.js
end
end
In my routes.rb I modified contact_infos by adding collection do...
resources :contact_infos do
collection do
get 'get_full_fields'
end
end
I created contact_infos\get_full_fields.js.erb:
var full_fields_form = $('<%= j(render(:partial => "contact_infos/full_name_info"))%>');
$('#test').html(full_fields_form);
Now when I test this in the browser with debugger and change SubCategory to "Full" I can see that it runs correctly (I think) in that I'm getting this back:
Request URL:http://localhost:3000/contact_infos/get_full_fields?contact_info%5Bsubcategory_id%5D=3
Request Method:GET
Status Code:200 OK
The "Type" is showing up as "text/javascript." The Response tab is just showing the javascript code but nothing is happening/triggering. Even when I place just a
alert('hello');
in the js file nothing happens.
Any ideas why?
Why not do it the same way you get subcategory data? Create a view containing the partial (and corresponding controller action) and call it via ajax when you want to display that content.

Resources