Rails 4 ajax: request being submitted too many times - html

I am trying to incorporate AJAX into my rails application when a user clicks the 'add to order' button. I want the item to get added to the order without the page reloading. When I click 'add to order', the ajax request gets sent multiple times resulting in many items being added to my order instead of just 1 item.
Here is my link_to tag that triggers an ajax request:
<%= link_to ' ', :method => :post, :remote => true %>
Here is the code for my 'products' controller and the 'buy' action:
def buy
respond_to do |format|
format.html { redirect_to ' ' }
format.js
end
From my understanding, the default rails action will be to load the app/views/products/buy.js.erb file and execute the commands in that file.
Here is what I have in that file:
$("#order-panel").html("").append("<%= j render 'order_summary' %>");
I am essentially overriding the previous html with the new template in this file:
_order_summary.html.erb
This partial contains the following code:
<div class="panel-heading">
<span class='glyphicon glyphicon-tags'></span><span class="text">Order Summary</span>
</div>
<div class="panel-body">
<% if current_order %>
<% if current_order.total_items == 0 %>
<div class="order-summary-text empty-order">Your order is empty.</div>
<% else %>
<div class="order-summary-text">yadayada</div>
<div class="order-btns">
<%= link_to ' ' %>
<%= link_to ' ' %>
</div>
<% end %>
<% end %>
Does anyone know why my multiple items are getting added instead of 1?
Thanks in advance!

Related

Multiple radio buttons getting selected in Rails app

I have an app where Question model has_many relationship with Option. I also have a button to add options while creating a question. Every question has only one correct answer. So when I create a question and click on Add Option button, new option is created but the new radio button associated with it has different name. In fact the name of radio button is of the form question[options_attributes][i][is_answer] where i is id. As far as I know radio buttons should have the same name to work as a collection or group. So how can I make it work as a group even if I create any number of options for a single question?
html.erb
<%= form_for #question do |form| %>
<div class="field">
<%= form.label :body %>
<%= form.text_area :body %>
</div>
<%= form.fields_for :options, question.options.each do |a| %>
<div class="field">
<%= a.label :options %>
<%= a.text_area :body %>
<%= a.radio_button :is_answer, "options" %>
<%= a.check_box :_destroy %>
<%= a.label :_destroy, 'delete' %>
</div>
<% end %>
<%= form.submit 'Add option', :name => "add_option" %>
<%= form.submit 'Delete options', :name => "remove_option" %>
<div class="actions">
<%= form.submit %>
</div>
<% end %>
controller.rb
class QuestionsController < ApplicationController
def new
#question = Question.new
#question.options.build
end
def create
#question = Question.new(question_params)
#question.user = current_user
if params[:add_option]
#question.options.build
else
respond_to do |format|
if #question.save
format.html { redirect_to #question, notice: 'Question was successfully created.' and return }
format.json { render :show, status: :created, location: #question }
else
format.html { render :new }
format.json { render json: #question.errors, status: :unprocessable_entity }
end
end
end
render :action => 'new'
end
private
# Use callbacks to share common setup or constraints between actions.
def set_question
#question = Question.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def question_params
params.require(:question).permit(:body, options_attributes: [:id, :body, :question_id, :created_at, :updated_at, :is_answer])
end
end
There are two options:
Using JavaScript on the client-side to uncheck the radio buttons.
Using radio buttons with the same name. It this case you will have to change the way you pass the :is_answer parameter and manually assign the value in options_attributes.
Method 1 details:
See this question radio different names - only check one
Method 2 details:
Instead of passing :is_answer parameter for each option you can pass a single parameter for the question having chosen answer id as the value. Lets name it "answer_id". We want this parameter to be in the params[question]
hash in the controller, so the whole name will be "question[answer_id]". Although radio buttons are generated for each option, only the chosen one will be sent to the server as they all have the same name.
<%= form.fields_for :options, question.options.each do |a| %>
<div class="field">
<%= a.label :options %>
<%= a.text_area :body %>
<%= radio_button_tag "question[answer_id]", a.object.id, a.object.is_answer? %>
<%= a.check_box :_destroy %>
<%= a.label :_destroy, 'delete' %>
</div>
<% end %>
https://apidock.com/rails/v4.2.7/ActionView/Helpers/FormTagHelper/radio_button_tag
In the controller you will have to manually assign the option's is_answer parameter based on the answer_id value.
def question_params
result = params.require(:question).permit(:body, :answer_id, options_attributes: [:id, :body, :question_id])
answer_id = result.delete(:answer_id)
result[:options_attributes].values.each do |option_attrs|
option_attrs[:is_answer] = option_attrs[:question_id] == answer_id
end
result
end
If you need further details please let me know. I will update the answer to give more information.

HTML/Ruby On Rails: Execute redirect automatically?

I have a page with the following code:
<div>
<% if #site.roster_management_enabled? %>
<h3><%= link_to "Go To Page", { :controller => 'roster_player_import', :action => 'rostering_redirect'}, :target => "_blank" %></h3>
<% end %>
</div>
The controller/action mentioned above is as follows:
def rostering_redirect
url = URI.join(#site.boss_organization.admin_app_root_url, 'rostering')
redirect_to url.to_s
end
I want the html code listed above to execute automatically rather than having the user click on the link. To be more specific, is there a way to return the URL from the controller/action and pass that to the HTML code such that I don't have to use the syntax {:controller =>.....} and instead use something like URL=....
You can put the url you redirect to directly in your template:
<div>
<% if #site.roster_management_enabled? %>
<h3><%= link_to 'Go To Page', URI.join(#site.boss_organization.admin_app_root_url, 'rostering').to_s, target: '_blank' %></h3>
<% end %>
</div>
This works if:
#site is available in the template (from your code it is not clear where it is loaded)
You do not need to run additional checks/tracking on the server side

if else condition using three models rails

I have 3 models
Users: id , name
Jobs: id, user_id, title
Applications: id, job_id, user_id
In Job#show page I am trying to put a button which is visible only to people who haven't applied to the job, haven't created the job and are logged in . I am using devise. I have managed to build correct relationship in these models (thanks to SO) as following.
user.jobs #list all jobs posted by the user
jobs.applicants #list all applicants on the job
Question is how to formulate if else condtion which shows button which submits a form (hidden) to the job#show page and puts job_id and user_id in the application model.
I tried
<% if user_signed_in? %>
<% if job.user_id = current_user.id %>
<div style="text-align:center;" class="widget">
<%= link_to(new_user_session_path, :class => "g-btn type_primary") do %>
<i class="icon-external-link"></i> Apply for the job
<% end %>
</div>
<% end %>
<% end %>
I can't seems to get the idea on how to get around error of object.id nil.
You seem to have missed an = sign.
You can improve your if condition like this
<% if user_signed_in? && job.present? && job.user_id == current_user.id %>
your logic here
<% end %>
how does a user apply for the job? using what controller?
you code has the user logging in again,
does the user need to create an application object and does it require additional information from the user to complete the process, or is more along the lines of send existing information from the user to information stored in the job.
If the latter you can do something like this.
resources :jobs do
member do
post 'apply'
end
end
<% if user_signed_in? %>
<% unless job.user == current_user %>
<div style="text-align:center;" class="widget">
<%= link_to 'Apply', apply_job_path(job), method: :post %>
</div>
<% end %>
<% else %>
<%= link_to 'Sign in to apply', new_user_session_path %>
<% end %>
then in your jobs controller
def apply
if Application.create job_id: params[:job_id], user: current_user
redirect_to jobs_path, notice: "You have applied, good luck!"
else
... do something for failure...
end
end
Try this instead
<% if user_signed_in? %>
<% if job.user_id == current_user.id %>
<div style="text-align:center;" class="widget">
<%= link_to "Apply for the job" new_user_session_path, :class => "g-btn type_primary" %>
</div>
<% end %>
<% end %>
and it might be better to change this line
<div style="text-align:center;" class="widget">
to
<div class="widget center">
and add a class named center to the relevant css sheet

How can I populate a div with Rails code when a link is clicked?

I'm trying to populate some li tags with this code:
<% #events.each do |event| %>
<li>
<span class="eventname"><%= event.name %></span>
<span class="eventlocation"><%= event.location %></span>
</li>
<% end %>
And I have some links that say "today", "tomorrow" etc and when I hit today I want the events from today to show up. If I hit tomorrow I want tomorrow's to show up. I've looked everywhere through AJAX tutorials and javascript tutorials and I'm completely lost on how to do this in rails.
One way I considered doing is having this block of code be a partial, and change it slightly for each partial so that the specific events that I want to show come up. But then I'm still stuck with the same problem, I'm not sure how to show a specific partial based on the click of a link.
We will have one partial that would render a set of given events (any type) let's call it _events.html.erb
_events.html.erb:
<% events.each do |event| %>
<li>
<span class="eventname"><%= event.name %></span>
<span class="eventlocation"><%= event.location %></span>
</li>
<% end %>
Then we would create an action named fetch_events that returns a js response.
Class EventsController < ApplicationController
def fetch_events
#events = Event.where(type: params[:type])
respond_to do |format|
format.js
end
end
end
ofcourse in routes.rb
match 'fetch_events/:type' => 'events#fetch_events', as: :fetch_events
now we build out fetch_events.js.erb, this file will set the contents of the div with id 'events' to the rendered partial.
fetch_events.js.erb:
$('#events').html(<%= escape_javascript(render :events, events: #events) %>)
Now in your page view add a have div with id 'events' that will contain the response, while
the ajax could be called using link_to
<%= link_to 'today', fetch_events_path(type: :today), :remote => true %>
<%= link_to 'tomorrow', fetch_events_path(type: :tomorrow), :remote => true %>

Placing link at top

How do I place a link at the top of my page when the URL that it is pointing to is not determined until later down the page. In this example, I want to move Create and Edit Scenario links to the top of the page, but as you can see Edit Scenario depends on knowing the #scenario_id first.
<%= will_paginate #scens, :next_label => 'Older', :prev_label => 'Newer' %>
<div class="box">
<% for scenario in #scens %>
<% #created = scenario.created_at %>
<% #updated = scenario.updated_at %>
<% #scenario_id = scenario.id %>
<% if scenario.scenario_image.exists? %>
<%= scenario_image_tag(scenario) %>
<% end %>
<%= simple_format(scenario.description) %>
<% end %>
</div>
<% if session[:role_kind] == "controller" %>
<p>
<%= button_to "Create new scenario", :action => "create" %>
<% if #scens.size > 0 %>
<%= button_to "Edit scenario", :action => "edit", :id => #scenario_id %>
<% end %>
</p>
You can add the link at the top but you will need to programmatically access it later and then assign the URL to it. That needs some kind of reference or look-up capability, I'm thinking client-side javascript but that's as I don't know Ruby.
Alternatively you could create the link later when you have the URL and place the link at the top using CSS positioning. The actual position of all the DOM elements on the page need not match the order in which they are rendered.
One way to do this is to use a helper:
In your helper.rb file:
def stack_example(scens, &block)
html = 'Scenario Details'
edit_link = 'Edit Link'
yield html, edit_link
end
Then in your partial you could have something like:
<% stack_example(#scens) do |html, edit_link| %>
<%= edit_link %><br>
<%= html %>
<% end %>
Should output the following:
Edit Link
Scenario Details
I don't get it. Why do you create model in the view layer? Why wouldn't you create the model variables in the controller? Sth like:
class your_controller
def your_method
#scenario_id = ...
end
end
I think that your problem lays in the invalid MVC usage. Don't you think that all the #member #variables should be initialized before the view starts to render?