Connect Multiple Yields in Rails - ruby-on-rails

Rails Newbie. Be gentle. If I need to show more stuff I'll do it.
Trying to insert a newsletter signup block above my footer on a project but didn't make it a partial in the layouts set up.
I have the yield outputting an index from a blog.
Right now it's just saying "false" on my local host.
Is it possible to have multiple yields to different indexes?
Is it possible to insert another page into a layout page?
application.html.erb
<div id="blog">
<%= yield %>
</div>
<div>
<%= content_for?(:newsletter) ? yield(:newsletter) : yield %>
</div>
<div>
<%= render 'layouts/footer' %>
</div>
newsletter.html.erb
<% content_for :newsletter do %>
<h1>Get My Awesome News Letter</h1>
<p>Give me your email and keep up to date on my cat's thoughts.</p>
<%= form_tag('/emailapi/subscribe', method: "post", id: "subscribe", remote: "true") do -%>
<%= email_field(:email, :address, {id: "email", placeholder: "email address"}) %>
<%= submit_tag("Sign me up!") %>
<% end %>
emailapi_controller.rb
class EmailapiController < ApplicationController
def newsletter
render params[:newsletter]
end
def subscribe
gb = Gibbon::Request.new
gb.lists.subscribe({
:id => ENV["MAILCHIMP_LIST_ID"],
:email => {:email => params[:email][:address]}
})
end
end
routes.rb
root to: 'posts#index'
get "/:newsletter" => 'emailapi#newsletter'
post 'emailapi/subscribe' => 'emailapi#subscribe'

You shouldn't need this conditional test:
content_for?(:newsletter) ? yield(:newsletter) : yield
try just:
<%= content_for :newsletter %>
Here's the doc on content_for:
http://apidock.com/rails/v4.2.1/ActionView/Helpers/CaptureHelper/content_for
Ie only show the newsletter if newsletter is present.
The extra yield (if newsletter-content is not present) is repeated from the blog-section above.
You probably shouldn't have duplicate plain yields just the one... everything else should have a name (eg :newsletter)
Also - you seem to be missing an <% end %> in newsletter.html.erb

You should be able to just use another render block. I'm not sure where your newsletter.html.erb lives, but if, for example it lived in a folder such as includes/ you could do something like:
<%= render 'includes/newsletter' %>

Related

My Rails button is not updating the database

I created a button where users can input stuff in a field and then press the button to update the database (put request) which can be seen here in show.html.erb:
<% provide(:title, #user.name) %>
<div class="row">
<aside class="col-md-4">
<section class="user_info">
<h1>
<%= gravatar_for #user %>
<%= #user.name %>
<br>
<%= #user.email %>
<% if #errors %>
<p>THE FORM COULD NOT BE SAVED </p>
<ul id='errors'>
<% #errors.each do |error| %>
<li><%= error %></li>
<% end %>
</ul>
<% end %>
<br>
<% if is_admin? %>
<% if !#user.admin %>
<div class="row">
<div class="col-md-6 col-md-offset-3">
<%= form_for(#user) do |f| %>
<%= f.label :wistia_project_id %>
<%= f.text_field :wistia_project_id, class: 'form-control' %>
<%= f.submit "Save", :action => "set_wistia_project_ID", :method => :patch, :form_class => "form-control" %>
<% end %>
</div>
</div>
<% end %>
<% end %>
</h1>
</section>
</aside>
</div>
The function is in user_controller.rb:
# Sets wistia_project_ID.
def set_wistia_project_ID
#user = User.find(params[:id])
#user.set_project_id
unless #user.valid?
#errors = #user.errors.full_messages
render :show
end
end
That function calls another function, just to separate things more clearly. This other function lives in user.rb:
# Sets the wistia_project_ID.
def set_project_id!(val)
self.wistia_project_ID = val # self is necessary here
save # or self.save, but the self is unnecessary here
end
My routes.rb:
.
.
.
resources :users do
member do
patch 'set_wistia_project_ID'
end
end
My problem is that right now, when you press the button, it says: Completed 500 Internal Server Error in 26ms (ActiveRecord: 0.7ms)
and
NoMethodError (undefined method `set_project_id' for #<User:0x000055b1a0914ab8>
2019-06-26T14:46:34.940086+00:00 app[web.1]: Did you mean? wistia_project_id):
Zavitoski got it right. I suggest, however, that you're doing a number of things more fundamentally wrong. Given that you're early in your rails journey, I hope you don't mind if I point a few things out.
First, and to be nit-picky, yes, you created a button. But, it is not a button "where users can input stuff in a field and then press the button to update the database". You created a button on a form. And you created a field on that form. The user can input stuff into the field. And when clicked, the button submits the form which includes the information in the field.
Now, on that form, you did:
<%= form_for(#user) do |f| %>
<%= f.label :wistia_project_id %>
<%= f.text_field :wistia_project_id, class: 'form-control' %>
<%= f.submit "Save", :action => "set_wistia_project_ID", :method => :patch, :form_class => "form-control" %>
<% end %>
There are a few things wrong with:
:action => "set_wistia_project_ID"
First, set_wisteria_project_ID is not a very ruby-ish action name. set_wistia_project_id would be more like it. Also, you're using old-form key-value formatting. And, you can use a symbol instead of a string for your action name so your code is prettier. Something, perhaps, like:
<%= f.submit "Save", action: :set_wistia_project_id, method: :patch, form_class: "form-control" %>
But, that's a mistake, too. Because you don't need a set_wistia_project_id action. (It's an action or a method, not a function.) You already have the update action. And form_for is smart enough to submit to this action if #user is an instance of User. So, really, you should do:
<%= form_for #user do |f| %>
<%= f.label :wistia_project_id %>
<%= f.text_field :wistia_project_id, class: 'form-control' %>
<%= f.submit "Save", form_class: "form-control" %>
<% end %>
I'm not sure what form_class is, but I'll trust that it's correct.
Now, in your UsersController, just do:
class UsersController < ApplicationController
def update
#user = User.find(params[:id])
if user.update(user_params)
# do something successful
else
# do something unsuccessful
end
end
private
def user_params
# NOTE: You'll probably want to permit other stuff here, too.
params.require(:user).permit(:wistia_project_id)
end
end
Get rid of this:
class User < ApplicationRecord
# Sets the wistia_project_ID.
def set_project_id!(val)
self.wistia_project_ID = val # self is necessary here
save # or self.save, but the self is unnecessary here
end
end
Because you're just duplicating the update method. And, you probably want that attribute to be wistia_project_id, not wistia_project_ID. (Again, you never see _ID as the suffix in rails core and you might as well be conventional.) And, if you make sure you have your association set up correctly, ActiveRecord should make sure that wistia_project_id is actually a valid value.
And write your routes.rb like this:
resources :users
Because you don't need all that set_wistia_project_id business.
It appears that you are not calling the function by the name you defined, neither passing the parameter (project_id) needed.
def set_wistia_project_ID
#user = User.find(params[:id])
#user.set_project_id!(params[:wistia_project_id])
unless #user.valid?
#errors = #user.errors.full_messages
render :show
end
end
This should use the function you created and pass the parameter from the form.

Missing required keys: [:id] - Routing to a view for each instance of my model with its unique ID

I'm working on a job board to learn/practice rails. I have a separate view for each job category, and I want the user to be able to click on a particular job posting to access another view with all of the listing's details. I've partially figured out the routing, as I'm able to go to localhost:3000/jobs/listing/7 for example to see the view for the listing of id:7. I'm having a problem linking to the /listing/:id from my job category view, and can only access a view for a specific id by typing it into the address bar. I've been working on this for days and checked out many related questions on here, but can't seem to figure it out. I believe I'm overlooking a simple, but critical detail, since i'm not very experienced with rails.
Here is my job category view:
<div class="cat-banner" id="developer">
<h1>Human Resources Jobs</h1>
<h4 class="listing-count"><%= Job.where(:category => 'Human Resources').count.to_s + ' Listings' %></h4>
</div>
<div class="category-page">
<!-- Full-Stack Developer Jobs -->
<div class="jobs-posted">
<hr class="other-line">
<% if Job.where(:category => 'Human Resources').count > 0 %>
<% #jobs.each do |job| %>
<div class="job">
<% if job.category == "Human Resources" %>
<span class="job-logo"><%= image_tag('salesforce.png', :size => "60x40") %></span>
<span id="line-align"><p class="title"><%= link_to job.title, listing_path(#job) %> </p>
<p class="name"><%= job.name %></p></span>
<% if job.location == "Remote" %>
<span class="remote-tag"><%= job.location.upcase %></span>
<% else %>
<p class="location"><%= job.location %></p>
<% end %>
<p class="kind"><%= job.kind %></p>
<p class="time-stamp"><%= job.created_at.strftime("%A, %B %d %Y") %></p>
<hr class="line">
<% end %>
</div>
<% end %>
<% else %>
<p>There are no human resources jobs at the moment...</p>
<p style="text-decoration: underline;"><%= link_to 'Post a Human Resources Job Here', new_job_path %></p>
<% end %>
</div>
<!-- End of Human Resources Jobs -->
</div>
And my routes.rb file:
Rails.application.routes.draw do
get 'subscribers' => 'subscribers#index'
get 'jobs/remote' => 'jobs#remote'
get 'jobs/listing/:id' => 'jobs#listing', as: 'listing'
get 'jobs/company' => 'jobs#company'
get 'jobs/dev' => 'jobs#dev'
get 'jobs/design' => 'jobs#design'
get 'jobs/marketing' => 'jobs#marketing'
get 'jobs/ai' => 'jobs#ai'
get 'jobs/fullstack' => 'jobs#fullstack'
get 'jobs/frontend' => 'jobs#frontend'
get 'jobs/backend' => 'jobs#backend'
get 'jobs/it' => 'jobs#it'
get 'jobs/software' => 'jobs#software'
get 'jobs/product' => 'jobs#product'
get 'jobs/cloud' => 'jobs#cloud'
get 'jobs/mobile' => 'jobs#mobile'
get 'jobs/database' => 'jobs#database'
get 'jobs/datascience' => 'jobs#datascience'
get 'jobs/blockchain' => 'jobs#blockchain'
get 'jobs/security' => 'jobs#security'
get 'jobs/support' => 'jobs#support'
get 'jobs/network' => 'jobs#network'
get 'jobs/finance' => 'jobs#finance'
get 'jobs/sales' => 'jobs#sales'
get 'jobs/hr' => 'jobs#hr'
get 'jobs/businessdev' => 'jobs#businessdev'
resources :jobs
root 'jobs#index'
get 'jobs/index'
get 'jobs/new'
And part of the Jobs Controller:
class JobsController < ApplicationController
def index
#jobs = Job.all
#subscribers = Subscriber.all
end
def new
#job = Job.new
end
def listing
#job = Job.find(params[:id])
end
def show
#job = Job.find(params[:id])
end
def create
#job = Job.new(params.require(:job).permit(:title, :url, :category, :kind, :location, :description, :name, :summary, :website, :email, :companyDescription, :headquarters ))
if #job.save
redirect_to root_path
else
render "new"
end
respond_to :html, :json
end
I've tried:
<%= link_to job.title, listing_path(#job) %>
<%= link_to job.title, listing_path(#job.id) %>
<%= link_to job.title, listing_path(#job[:id]) %>
<%= link_to job.title, listing_path %>
and other variations that I thought would work from reading StackOverflow
I believe my problem comes from this link_to statement (wrong syntax?), as everything looks alright in my jobs controller and routes file.
I either get:
No route matches {:action=>"listing", :controller=>"jobs", :id=>nil}, missing required keys: [:id],
or
undefined method `id' for nil:NilClass,
or
undefined method `[]' for nil:NilClass
The "missing required keys: [:id]" error is confusing me. I've checked out many resources trying to figure out how to pass the :id but can't solve it.
This is my first post on here and I REALLY appreciate any help and look forward to being knowledgeable enough in the future so I can answer questions too.
rake routes
The view that you are putting as example is using the instance variable #jobs. According with your controller that would be your index action where you don't have #job defined
Note: Notice on that view you are using #jobs and job on your iterator
So I think if you change #job for job that would fix the problem on that view
<%= link_to job.title, listing_path(job) %>
As the error clearly states, your path is expecting a job id but it is not getting one, so inspecting your call for the path, in line:
<span id="line-align"><p class="title"><%= link_to job.title, listing_path(#job) %> </p>
you are passing #job as param to the listing path.
change it to job so it would be:
<span id="line-align"><p class="title"><%= link_to job.title, listing_path(job) %> </p>
For the missing id, you should do:
<%= link_to job.title, listing_path(id: #job) %>
since your id is stored in the variable #job
It seems that the reason this isn't working is because you are not sending the correct argument to your link_to here:
<%= link_to job.title, listing_path(#job) %>
You have to remember that you are iterating through all your #jobs and calling each individual job with the job variable between the | |. You are trying to create a link to each individual job, so the correct link_to should be:
<%= link_to job.title, listing_path(job) %>
Where job is the individual job that the link_to is looking for.

Rails 5 fields_for only sends last params

I have been hitting my head against a brick wall so it is time to seek smarter people.
I am trying to create multiple records of one model using form_tag and fields_for. I have been following all the help/issues/guides I can find but it doesn't seem to work for me. I am wondering if it something that changed going to Rails 5 but more likely it is me.
Basically I want a new/create version of the task system listed at the bottom of the api page, similar to this guys puppy creator.
The "new" page loads fine with as many records as I like, so that part is ok but it doesn't seem to be creating a collection to send through, it is just overriding and thus sending through the last set of params so only creating one record.
What I have.
# routes
resources :container_returns
controller
# container returns controller
def new
#containers = Container.where(id: params[:container_ids])
#container_returns = []
#containers.each do |container|
#container_returns << ContainerReturn.new(
{
container_id: container.id,
quantity: container.amount,
uom: container.uom,
material_restriction_id: container.material_restriction_id
}
)
end
end
view
# new.html.erb
<%= form_tag container_returns_path, method: :post do %>
<% #container_returns.each do |container_return| %>
<%= fields_for 'returns[]', container_return, hidden_field_id: true do |cr| %>
<div class="field">
<%= cr.label :container_id %>
<%= cr.number_field :container_id %>
</div>
<div class="field">
<%= cr.label :material_restriction_id %>
<%= cr.number_field :material_restriction_id %>
</div>
<div class="field">
<%= cr.label :quantity %>
<%= cr.text_field :quantity %>
</div>
<div class="field">
<%= cr.label :uom %>
<%= cr.text_field :uom %>
</div>
<% end %>
<% end %>
<%= submit_tag "lots of returns" %>
<% end %>
which submits
# params submitted
Started POST "/container_returns" for 127.0.0.1 at 2018-10-19 11:00:48 +0200
Processing by ContainerReturnsController#create as HTML
Parameters: {
"utf8"=>"✓", "authenticity_token"=>[removed],
"returns"=>{"container_id"=>"405", "material_restriction_id"=>"", "quantity"=>"100.0", "uom"=>"kg"}, "commit"=>"lots of returns"
}
hopefully it is just something stupid that I missed.
UPDATE:
if I add an index to the form it now believes me that my objects are different and sends through all the params I need.
<% #container_returns.each_with_index do |container_return, index| %>
<%= fields_for 'returns[]', container_return, index: index do |cr| %>
[...]
as mentioned in the update, if I add an ID to the initial create it builds the correct array that I was expecting. What I also found was if I send through an index position that also works.
<% #container_returns.each_with_index do |container_return, index| %>
<%= fields_for 'returns[]', container_return, index: index do |cr| %>
[...]
gives me what I was expecting
Parameters: {
"returns"=>{"0"=>{"container_id"=>"400",...},
"1"=>{"container_id"=>"401",...},
etc.
},
"commit"=>"lots of returns"
}

How can I dynamically update search results based on form input in Rails?

I want site visitors to be able to view nearby shows within a radius that can be input via dropdown form. I have a view that displays nearby shows using the Geocoder gem:
<h3> Shows near <%= request.location.city %> </h3>
<%= form_for #nearby_shows.first do |f| %>
<p> Radius (in miles): <%= f.select(:radii, [10,20,30,40,50], {},
:style => "width:50px", :selected => f.object.radii, :onchange =>
"location.href = '#{shows_path}'") %> </p>
<% end %>
<ul class="users">
<% #nearby_shows.each do |nearby_show| %>
<li>
<%= link_to nearby_show.show_name, nearby_show %>
</li>
<% end %>
</ul>
Right now the selection doesn't affect anything, and the selection isn't remembered in the form when the page refreshes.
The model, show.rb contains:
attr_accessor :radii
And the shows controller contains:
def index
#shows = Show.all
#radii = 50
#nearby_venues = Venue.near("Boulder, CO",#radii,:select =>
"id").to_a
#nearby_shows = Show.where(show_venue: #nearby_venues)
end
In production, I'll be using request.location.city, but in development I'm just using "Boulder, CO" as an example.
How can I set #radii using the input select form? I am concerned that form_for will not permit me to change a variable for the list of entities #nearby_shows.
If you want a fast AJAX solution, here's what I would do
First, add an ID to your list so it's easy to manipulate
<ul id="my_id" class="users"></ul>
I really don't understand why you need that <%= form_for #nearby_shows.first %> for ? If I understand well, you just want to show a select, and update the list of nearby shows based on what the user selects ?
routes.rb
resource :shows do
get 'update_nearby', on: :collection, constraints: { format: 'js' }
end
# GET /shows/update_nearby, meant to be used only with AJAX
your_view.html.erb
<%= form_tag update_nearby_shows_path, remote: :true do |f| %>
<p> Radius (in miles): <%= select_tag(:radii, [10,20,30,40,50], {},
:style => "width:50px", :selected => #radii, :onchange =>
"location.href = '#{shows_path}'") %> </p>
<% end %>
<!-- On Submit, it will request a JS response
You can add some JS to submit the form everytime the select changes -->
Add some JS specific respone
your_controller.rb
def update_nearby
find_nearby_shows
end
private
def find_nearby_shows
#radii = params[:radii] ? params[:radii] : 50
#nearby_venues = Venue.near("Boulder, CO",#radii,:select =>
"id").to_a
#nearby_shows = Show.where(show_venue: #nearby_venues)
end
update_nearby.js.erb
<% if #nearby_shows %>
// Empty the list
var id = $("#my_id").empty()
<% #nearby_shows.each do %>
// Add one <li> per show
$("<li>", { 'html': "<%= escape_javascript(link_to(nearby_show.show_name, nearby_show)) %>"}).appendTo(id)
<% end %>
<% end %>
Bonus : you said you wanted to save the radius ? You can actually try to add it to the user session
def index
...
#radii = session[:saved_radii] ? session[:saved_radii] : DEFAULT_RADIUS
...
end
def update_nearby
find_nearby_shows
session[:saved_radii] = #radii
end
But if you really want to save it for the user, you should have a preferred_radii field in your User model

How do I implement a show all comments feature in ruby on rails?

I'm implementing show/hide feature for users comments.
Discussed here: https://stackoverflow.com/a/10174194/439688
My aim was to:
1. Limit the default shown comments to 2.
2. Have a span with text that states the number of total comments for that particular micropost and when clicked by a user have it expand and show all comments for that micropost. I would be using Jquery/Ajax to hide, show, prepend etc.
The first change was to limit the amount of comments shown to the user and I achieved this by creating a method in my helper called "comments" and here I pass in the id of the micropost the comment belongs to.
def get_comments(micropost_id)
Comment.limit(2).order("created_at DESC").where(:micropost_id => micropost_id)
end
Now the each loop that loops through each comment will only show the 2 most recent comments.
<<% #microposts.each do |m| %>
<% if m.poster_id.nil? %>
<div class="postHolder">
<nav class="micropostOptions">
<ul class="postMenu">
<li class="deletePost"><%= link_to content_tag(:span, "Delete post"), m, :method => :delete, :confirm => "Are you sure?", :title => m.content, :class => "message_delete", :remote => true %>
</li>
<li class="disableCommenting"><%= link_to content_tag(:span, "Pause commenting"), "2" %></li>
<li class="blockCommenter"><%= link_to content_tag(:span, "Block commenter"), "3" %></li>
<li class="openInNewWindow"><%= link_to content_tag(:span, "Open in new window"), "4" %></li>
<li class="reportAbuse"><%= link_to content_tag(:span, "Report abuse"), "5" %></li>
</ul>
</nav>
<%= link_to image_tag(default_photo_for_current_user, :class => "poster_photo"), current_users_username %>
<div class="post_content">
<div class="post_container">
<div class="mainUserNameFontStyle"><%= link_to current_users_username.capitalize, current_users_username %> - <div class="post_time"> <%= time_ago_in_words(m.created_at) %> ago.</div>
</div>
<%= simple_format h(m.content) %> </div>
<div class="commentsCount">
<%= content_tag :span, pluralize(m.comments.count, 'comment'), :class => "view_all_comments" if m.comments.any? %>
</div>
<% if m.comments.any? %>
<% comments(m.id).each do |comment| %>
<div class="comment_container">
<%= link_to image_tag(default_photo_for_commenter(comment), :class => "commenter_photo"), commenter(comment.user_id).username %>
<div class="commenter_content"> <div class="userNameFontStyle"><%= link_to commenter(comment.user_id).username.capitalize, commenter(comment.user_id).username %> - <%= simple_format h(comment.content) %> </div>
</div><div class="comment_post_time"> <%= time_ago_in_words(comment.created_at) %> ago. </div>
</div>
<% end %>
<% end %>
<% if logged_in? %>
<%= form_for #comment, :remote => true do |f| %>
<%= f.hidden_field :user_id, :value => current_user.id %>
<%= f.hidden_field :micropost_id, :value => m.id %>
<%= f.text_area :content, :placeholder => 'Post a comment...', :class => "comment_box", :rows => 0, :columns => 0 %>
<div class="commentButtons">
<%= f.submit 'Post it', :class => "commentButton", :disable_with => "Post it" %>
<div class="cancelButton"> Cancel </div>
</div>
<% end %>
<% end %>
</div>
</div>
From here this is where it gets confusing for me. I got slightly further using link_to but then decided I'd prefer not to have the url to the comments count show in the browser status bar. This is why I switched to using span.. but now it's not quite easy to do what I wish to do as I can't use the link_to/remote => true now.
How do I make it so when a user clicks the comment count span an ajax call is made pointing to:
def load_comments
#load_comments = Comment.where(:micropost_id => params[:id])
respond_to do |format|
format.js { render :load_comments }
end
end
I thought about putting a click function in users.js but how would I pass the params of the micropost that is in the each loop in the code above into users.js? I don't think it's possible.
All my comment posting is done via ajax but because I used forms for these it was so much easier for me to just add remote => true and create some js templates and do something on success of ajax post.
Not sure if I'm even going about this the right way. I'd appreciate some help/advice from more experienced rails programmers.
Kind regards
Rails partial
#Display all the comments based on local passed to this partial
# Initially pass limit as 2(or whatever you want). then on click of span pass limit as nil. then you can check if limit is nil you can query the model without limit specifier.
<% #comments = Comment.custom_find(#your_params) %>
<% #comments.each do |comment| %>
<%= comment.title %>
<% end %>
javascript/jquery
function load_all_comments(id)
{
new Ajax.Updater('show_comments',
'<%=url_for(:controller => "your_controller", :action => "your_action")%>', {
parameters: {'id':id },
method: 'get',
onSuccess: function(request){
div_comments = document.getElementById("partial_comments_list");
div_comments.innerHTML = request.responseText;
}
});
} // you can call this js function on span click. use jquery if you want.
Controller:
Then inside your_action of your_controller, dont forget to render the partial
render :partial => "show_comments", :layout => false
Edit:
you can even pass locals to your partial
render :partial => "show_comments", :locals => {:post => #post}
Using this every time your partial view will get updated, on the basis of locals you pass.
of course this is just an example not a complete code/solution.
There may be better ways. but this worked fine for me.
Another option is to just output all of the comments and hide the ones you don't want to show first. <div class="hidden_comments" style="display:none;"> a comment </div>
Then just have some javascript to show them when the span is clicked?
<script type="text/javascript">
$("#span_id").click(function() {
$('.hidden_comments').show();
});
</script>
This works great if you do not don't have a ton of comments.
If you really want to do it your way, I have done it before but it gets messy.
Put this in your application.js
$('.comment_span').live('click', function () {
$.get(this.data_url, null, update_row, 'json');
return false;
});
Your span would look like this:
<span class="comment_span" data_url="http://website.com/resource/more_comments">
show all comments
</span>
This example returns the data as json, so I used the update_row function to update replace the comments data.
function update_row(data, status) {
$("#comments-table").append(data.html);
};
Here is what my controller looked like:
def more_comments
#comments = Comments.all
if #comments
respond_to do |format|
format.js {
render :json => {
:html => render_to_string(:partial => "comments"),
}.to_json
}
end
end
end
You should do this via your index action.
Pass a param to it to determine if you want to show all comments or just the current set (I'd use will_paginate to handle this.
Haven't looked too deep into your code as I'm on my phone right now, but something like this:
class CommentsController < ApplicationController
def index
If params[:show_all] == "true"
#comments = Comment.all
else
#comments = Comment.where(foo: bar).paginate(per_page: 2, page: params[:page])
end
end
Then you have it respond to JavaScript and send the page param with your Ajax request

Resources