Ruby on rails variable AJAX - ruby-on-rails

What I want to do is pass a the value of the fields in the form to the controller so I can make a custom query in the db. I think something is missing but I just can't see what.
This is my controller
def index
#contributions = Contribution.all
#number1 = params[:number1]
#number2 = params[:number2]
#itemsok = Contribution.where("first_item_id = ?",#numer1).where("first_item_grade = ?",#numer2)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #contributions }
end
This is the view
<%= form_tag(contribution_path, :method => "get") do %>
<%= label_tag(:number1, "Number 1:") %>
<%= text_field_tag(:number1) %>
<%= label_tag(:number1, "Number 2:") %>
<%= text_field_tag(:number2) %>
<%= submit_tag("Searcs") %>
<% end %>
And this is the line in the routes.rb
get 'contribution' => 'contributions#index', :as => 'contribution'
Thank you very much.

Add :remote => true to the form tag to make it submit via ajax, and make sure to respond_to format.js in the controller action.
<%= form_tag(contribution_path, :remote => true) %>

Related

Update form from another scaffold

I am trying to update a record from the view of another scaffold, the problem is that it sends me the following error:
No route matches {:action=>"update", :controller=>"pedidosliberados"}
I'm showing one form per record
this is my form:
<% #pedidosliberados.each do |pedidoliberado| %>
<tr id="pedido_liberado_<%= pedidoliberado.id %>">
<td class="component_name_body_col"><%=pedidoliberado.try(:Client)%></td>
<td class="component_name_body_col">
<%= form_for(pedidoliberado, :method => :put, remote: true, :url => {:controller =>'pedidosliberados', :action => 'update'}, html: {class: "form-horizontal "}) do |f| %><!--ajax-->
<%= f.text_field :Status, value: "1" %>
<%= submit_tag "Actualizar", class: "btn btn-primary"%>
<% end %>
</td>
</tr>
<% end %>
my route:
resources :pedidosliberados
my action update from controller pedidosliberados:
def update
respond_to do |format|
if #pedidoliberado.update(pedidoliberado_params)
format.html { redirect_to #pedidoliberado, notice: 'Pedidoliberado was successfully updated.' }
format.json { render :show, status: :ok, location: #pedidoliberado
format.js {}
else
format.html { render :edit }
format.json { render json: #pedidoliberado.errors, status: :unprocessable_entity }
format.js {}
end
end
end
The problem is that you are using an incomplete route, that is /update; you need to add the id of the object to be updated, something like /update/12 where 12 is the id of the object. So in your code you could remove the :url attribute and you will be fine.
So your view, now should look like this:
<% #pedidosliberados.each do |pedidoliberado| %>
<tr id="pedido_liberado_<%= pedidoliberado.id %>">
<td class="component_name_body_col"><%=pedidoliberado.try(:Client)%></td>
<td class="component_name_body_col">
<%= form_for(pedidoliberado, :method => :put, remote: true, html: {class: "form-horizontal "}) do |f| %><!--ajax-->
<%= f.text_field :Status, value: "1" %>
<%= submit_tag "Actualizar", class: "btn btn-primary"%>
<% end %>
</td>
</tr>
<% end %>
This works because rails automatically assigns the correct controller and action for your object (when using REST routes).
UPDATE
If you want to explicity assign the url, then use :url like you are doing, but adding :id (remember, you need to specify the id of the object to be updated). So, your form should look something like this:
<%= form_for(pedidoliberado, method: :put, remote: true, url: { controller: 'pedidosliberados', action: 'update', id: pedidoliberado.id }, html: { class: "form-horizontal " }) do |f| %>

Rails: return only json

In my app there is a list of items which you can upvote. I want to make these votes with AJAX calls.
This is the view:
<ul class="list-groups">
<% #questions.each do |question| %>
<li class="list-group-item">
<%= link_to question.description, question_path(question) %>
<%= form_for(question, :url => url_for(:controller => 'vote', :action => 'vote'), method: :post, html: { class: 'form-inline' }) do |f| %>
<%= f.submit 'Up vote', class: "btn btn-default" %>
<%= f.hidden_field :id, :value => question.id %>
<% end %>
</li>
<% end %>
</ul>
And this the method that does it:
class VoteController < ApplicationController
respond_to :json
def vote
question_id = params[:question][:id]
user_id = current_user.id
vote = Vote.where(["question_id = :q", { q: question_id }]).where(["user_id = :u", { u: user_id }])
respond_to do |format|
if vote.nil?
#vote = Vote.new
#vote.question_id = question_id
#vote.user_id = user_id
#vote.save
format.html { render '/home/index' }
format.json { render :json => { :status => 'ok' } }
else
format.html { render '/home/index' }
format.json { render :json => { :status => 'failed', :msg => 'You already voted' } }
end
end
end
end
If I don't include this format.html { render '/home/index' } I am getting this error:
ActionController::UnknownFormat in VoteController#vote
But I don't want to render the page again, I am just loading the pieces of html that will change after the action with jQuery and ajax.
How can I respond only with the json?
Use respond_with instead of respond_to in your controller action.
respond_with do |format|
respond_to at the top of your controller is designed to work with respond_with in your controller action, whereas respond_to in your controller action ignores the respond_to that you've defined at the top of your controller.
Also make sure you are making a remote call, instead of a normall one if you want your request to go through AJAX.
<%= form_for(question, :url => url_for(:controller => 'vote', :action => 'vote'), method: :post, remote: true, html: { class: 'form-inline' }) do |f| %>
Note the remote: true part that is added as an argument to the form_for helper.
You need to include remote: true in form_for in order to make the call requests AJAX instead of HTML.
<%= form_for(question, :url => url_for(:controller => 'vote', :action => 'vote'), remote: true, method: :post, html: { class: 'form-inline' }) do |f| %>
Check out the Working with JavaScript in Rails documentation for more information.

Rails post delete functionality giving template error

I am trying to have a link to delete a certain reservation from the database. This is my solution but it keeps giving Template Error. It shouldn't render the view but it is.
def delete
#current = Reservations.find(params['reservations']['id'])
respond_to do |format|
if current_user
if #current.user_id == current_user.id
#current.destroy
format.html { redirect_to :back }
else
format.html { redirect_to root_path }
end
else
format.html { redirect_to root_path }
end
end
end
My routes file
post "reservations/delete", to: 'reservations#delete', as: 'delete_reservation'
My view that includes the delete link:
<%= form_for item, :url => {:controller => 'reservations', :action => 'delete'}, :method => 'post' do |f| %>
<%= f.hidden_field :id, :value => item.id %>
<%= f.submit "Delete", :class =>'btn btn-danger btn-small' %>
<% end %>

Instance Variable string collection lost after render => 'new'

When I get an error creating a quote, it renders the same page it was just on and displays the errors. Unfortunately two inputs are drop down menus of strings, and they disappear when the refresh happens.
I've looked at Rail 3: instance variable not available after redirection which talks about sessions, which looks like it could be the right way to go but I'm not sure. Any help would be appreciated.
quotes controller
def new
#quote = Quote.new
#quote.items.build
#types = ["T-Shirt", "Hoodie", "Sweatpants"]
#colors = ["White", "Black", "Red", "Blue", "Green"]
end
def create
#quote = Quote.new(params[:quote])
respond_to do |format|
if #quote.save
format.html { redirect_to root_url }
flash[:success] = "Your quote is being approved. You will recieve an email shortly!"
format.json { render json: #quote, status: :created, location: #quote }
else
format.html { render :action => 'new' }
format.json { render :json => #quote.errors, :status => :unprocessable_entry }
flash[:error] = "Quote failed to create! Try again!"
end
end
end
form partial
<!-- item form -->
<%= f.input :make, collection: #types, label: 'Thread Type' %>
<%= f.input :amount, label: 'How Many' %>
<%= f.input :color, collection: #colors %>
<!-- nested form for creating a design of an item -->
<%= f.simple_fields_for :designs, :html => { :multipart => true } do |designform| %>
<%= render "customdesign", g: designform %>
<% end %>
<!-- add/remove another design -->
<%= f.link_to_add "Add Design", :designs %>
<%= f.input :note, :input_html => { :cols => 50, :rows => 3 }, label: 'Special Notes or Requests' %>
<%= f.link_to_remove "Remove" %>
#colors and #types are only set in the new action, and not the create action. Rendering a template does not automatically call the action method in the controller; it goes straight to the view.
A possible solution is to define helper methods for these lists:
# app/helpers/quote_helper.rb
module QuoteHelper
def possible_types
["T-Shirt", "Hoodie", "Sweatpants"]
end
end
And in your view:
<%= f.input :make, collection: possible_types, label: 'Thread Type' %>

Rendering from another controller with AJAX

I have query to the db, where I ask for specific entries. This is the controller:
def index
#contributions = Contribution.all
#number1 = params[:number1]
#number2 = params[:number2]
#itemsok = Contribution.where("first_item_id = ?",#number1).where("first_item_grade = ?",#number2)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #contributions }
end
Ok and I have a form in the view wich allows me to pass data from the user input
<%= form_tag(contribution_path, :method => "get") do %>
<%= label_tag(:number1, "First Item Id") %>
<%= text_field_tag(:number1) %>
<%= label_tag(:number1, "First Item Grade") %>
<%= text_field_tag(:number2) %>
<%= submit_tag("Do it!" , :remote => true) %>
<% end %>
That works perfectly, but now I want to render this function from the main page index (display_controller, display index.html.erb). I gave all the properties to the display_controller like this:
class DisplayController < ApplicationController
def index
#items = Item.all
#contributions = Contribution.all
#number1 = params[:number1]
#number2 = params[:number2]
#itemsok = Contribution.where("first_item_id = ?",#number1).where("first_item_grade = ?",#number2)
respond_to do |format|
format.html # index.html.erb
format.json { render json: #contributions }
end
end
end
And I have the same form in the display view that is in the contributions view....
Right now what It does is that it redirects me to the contributions part, what I want t achive is to render the results in the display view...
Any thoughts? Thank you very much.
Sorry for my terrible english.
#
I got it
Got it the answer was to change in view the form to selected action
<%= form_tag(contribution_path, :method => "get") do %>
<%= label_tag(:number1, "First Item Id") %>
<%= text_field_tag(:number1) %>
<%= label_tag(:number1, "First Item Grade") %>
<%= text_field_tag(:number2) %>
<%= submit_tag("Do it!" , :remote => true) %>
<% end %>
Change it to
<%= form_tag(display_path, :method => "get") do %>
<%= label_tag(:number1, "First Item Id") %>
<%= text_field_tag(:number1) %>
<%= label_tag(:number1, "First Item Grade") %>
<%= text_field_tag(:number2) %>
<%= submit_tag("Do it!" , :remote => true) %>
<% end %>
In my case this was not working at the beginning but now I figured that it was because I have my display_path as the root_path so I changed it to...
<%= form_tag(root_path, :method => "get") do %>
<%= label_tag(:number1, "First Item Id") %>
<%= text_field_tag(:number1) %>
<%= label_tag(:number1, "First Item Grade") %>
<%= text_field_tag(:number2) %>
<%= submit_tag("Do it!" , :remote => true) %>
<% end %>
And now it works perfectly.
Can someone change this question to answered, I have like 21 of reputation and can't answer my own question. Tanks.
For better code quelity you should avoid repititions of code and make reusable, move that formm to a common partial view and use :url =>{:action => 'my_action'} in the form tag then you can use it any controller index view. While form action it will take the default controller from which it will be rendered.
share/_form.erb.html
<%= form_tag(:url =>{:action => 'my_action'}, :method => "get") do %>
<%= label_tag(:number1, "First Item Id") %>
<%= text_field_tag(:number1) %>
<%= label_tag(:number1, "First Item Grade") %>
<%= text_field_tag(:number2) %>
<%= submit_tag("Do it!" , :remote => true) %>
<% end %>
and in controller respective index view
index.erb.html
<%= render :partial 'share/form' %>
you can even declare variables for action and controller in your index method like
def index
// do something
#action = 'new_action'
#controller = 'new_controller'
// do some more thing
end
and then in form
:url =>{:controller => #controller, :action => #action}

Resources