Only get information in increments for Rails loop - ruby-on-rails

Given the code below:
var photos = [
<% current_app_user.photos.each do |photo| %>
{ url: "<%= photo.thumbnail_uri(400, 189) %>", title: "<%= truncate(photo.name, 65) %>", path :"<%= photo_path(photo) %>" },
<% end %>
];
How would I modify it to only pull 10 photos at a time?
Initially, I'd like to generate 10, then with the click of a button append 10 more and so on.

You should do this in a controller, not in your view, but inside a controller you should do it like this:
#photos = current_app_user.photos.all(:limit => 10).map do |p|
{ :url => p.thumbnail_uri(400, 189),
:title => p.name,
:path => photo_path(p) }
end
And in your view:
var photos = <%= #photos.to_json %>;
No code in your view other than what's strictly necessary :)

If you only want 10 results you could simply use the limit method:
current_app_user.photos.limit(10).each { |photo| # etc... }
If you need to get all the photos but chunk them into blocks of 10 and you're using jQuery you could this code that I created that adds a each_slice function to the core jQuery object. It might be useful in this situation.

Related

using the city-state gem in rails

Hey guys im currently working on a devise sign up form, the end goal is a user can select a state from the united states and a select tag below will populate with the correct cities in that state. im using the city-state gem. https://github.com/loureirorg/city-state
ive looked at other examples like this one https://forum.upcase.com/t/dependent-country-city-state/7038 my code is below
routes.rb
resources :states, only: :new
registrations.new.html.erb
<div class="field">
<%= f.select :state, options_for_select(CS.states(:us)), {:prompt => "State"}, {:class => "signup-input-container--input", :id => "state-picker"} %>
</div>
<div class="field">
<%= f.select :city, options_for_select([]),{}, {:class => "signup-input-container--input", :id => "city-picker"} %>
</div>
main.js
document.addEventListener("turbolinks:load", function(){
var state = document.getElementById("state-picker");
state.addEventListener("change", function() {
Rails.ajax({
url: "/states?country=" + "United States" + "&state=" +
state.value,
type: "GET"
})
})
});
registrations-controller.erb
def new
super
#cities = CS.get(:us, params[:state])
end
new.js.erb
var city = document.getElementById("city-picker");
while (city.firstChild) city.removeChild(city.firstChild);
var placeholder = document.createElement("option");
placeholder.text = "Choose a city";
placeholder.value = "";
city.appendChild(placeholder);
<% #cities.each do |c| %>
city.options[city.options.length] = new Option('<%= c %>');
<% end %>
im trying to get this to work the way the example link shows. the only difference is that users will only choose states from the US and citys
From our discussion in the comments the issue appears to be that you are requesting the wrong URL for your cities.
You have a route at /states/new but are making the request to /states. Try updating your main.js to:
document.addEventListener("turbolinks:load", function(){
var state = document.getElementById("state-picker");
state.addEventListener("change", function() {
Rails.ajax({
url: "/states/new?state=" + state.value,
type: "GET"
})
})
});
(I removed the country parameter in the URL because you don't seem to be using it, you say you only need this for the US anyway.)
Let me know how you get on with that.

Using js.erb in rails

In Rails 5 app with devise, I need to use a new.js.erb file to update select tag in my registrations view and controller. I cant seem to figure out why my new.js.erb file isn't working.
I've tried to use respond_to in controller as below,
registrations-controller.rb
def new
super
#cities = CS.get(:us,params[:state])
respond_to do |format|
format.js { render '/new.js.erb' }# layout: false }
format.html
end
end
new.html.erb
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), :remote => true) do |f| %>
<div class="signup-input-container">
<div class="field">
<%= f.text_field :firstname, autofocus: true, autocomplete: "firstname", placeholder: "First name", class: "signup-input-container--input" %>
</div>
<div class="field">
<%= f.select :state, options_for_select(CS.states(:us).map { |code, name| [name, code] }),{:prompt => "State"}, {:class => "signup-input-container--input", :id => "state-picker"} %>
</div>
<div class="field">
<%= f.select :city, options_for_select([]),{}, {:class => "signup-input-container--input", :id => "city-picker"} %>
</div>
</div>
<% end %>
new.js.erb
var city = document.getElementById("city-picker");
while (city.firstChild) city.removeChild(city.firstChild);
var placeholder = document.createElement("option");
placeholder.text = "Choose a city";
placeholder.value = "";
city.appendChild(placeholder);
<% #cities.each do |c| %>
city.options[city.options.length] = new Option('<%= c %>');
<% end %>
main.js
var state = document.getElementById("state-picker");
state.addEventListener("change", function() {
$.ajax({
url: "/states?state=" + state.value,
type: "GET"
})
})
I'm expecting this to create select tag options with my array of cities in my controller. Does anyone know how to get this to work?
To solve this you should just setup a separate controller where you can fetch the data from asynchronously and alternatively there are also several free API's which can be used for geographical lookup such as Googles Geocoding API and Geonames.
To setup a separate controller you can do it by:
# /config/routes.rb
get '/states/:state_id/cities', to: 'cities#index'
# /app/controllers/cities_controller.rb
class CitiesController < ApplicationController
# GET
def index
#cities = CS.get(:us, params[:state_id])
respond_to do |f|
f.json { render json: #cities }
end
end
end
I would skip using a .js.erb template altogether and just return JSON data which you can use directly in your JS or with one of the many existing autocomplete solutions. .js.erb only makes sense for extensive HTML templating (like for example rendering an entire form) where you want to reuse your server side templates - it greatly increases the complexity and generally makes a mess of your javascript which is not worth it just to output a list of option tags.
// If you are using jQuery you might as well setup a delegated
// handler that works with turbolinks,
$(document).on('change', '#state-picker', function(){
$.getJSON("/states/" + $(this).value() + "/cities", function(data){
// using a fragment avoids updating the DOM for every iteration.
var $frag = $('<select>');
$.each(data, function(city){
$frag.append$('<option>' + data + '</option>');
});
$('#city-picker').empty()
.append($('frag').children('option'));
});
});

Refresh div with gmaps4rails (AJAX)

I'm using Rails 3.0.9 version, and jquery.
I've been using this gem without a database. It is used only for map display, and display KML file on it. For this I used:
<div id='ajax_map'>
<% #kmlurl="http://mysite/file1.kml" %>
<%= gmaps( :kml => { :data => "[{ url: #{#kmlurl.inspect}}]" } ) %>
</div>
All great shows.
I want to do that after you change the links (# kmlurl), and click on the button, the map updated with this new KML file. I use a separate action js.erb with the following code:
$('#ajax_map').html('<%= #kmlurl="http://mysite/file2.kml" %>'+'<br />'+'<%= gmaps( :kml => { :data => "[{ url: #{#kmlurl.inspect}}]" } ) %>');
But he does not update the DIV. "js.erb" rendered normally, without using the method of gmaps () it normally returns # kmlurl. I tested this same code in the ". Html.erb" in the tags , it loads a new file, but, of course, just when the page loads.
How can I solve this problem?
Solved the problem as follows (in js.erb):
$('#ajax_map').html('<%= escape_javascript( gmaps({:last_map => false}) ) %>');
Gmaps.map = new Gmaps4RailsGoogle();
Gmaps.load_map = function() {
Gmaps.map.map_options.maxZoom = 15;
Gmaps.map.initialize();
Gmaps.map.kml = [{ url: '<%= "#{#kmlurl}" %>'}];
Gmaps.map.create_kml();
Gmaps.map.adjustMapToBounds();
Gmaps.map.callback();
};
Gmaps.loadMaps();
First I would refactor things just a bit.
Say that first bit of code were in your index page. I'd move the setting of #kmlurl into the corresponding controller action:
def index
#kmlurl = "http://mysite/file1.kml"
end
Then (assuming index?) your index view would be simply:
<div id="ajax_map">
<%= gmaps( :kml => { :data => "[{ url: #{#kmlurl}}]" } ) %>
</div>
Then to add a link that will update the map:
<%= link_to 'Other Map', '/othermap', :remote=>true %>
Now you'd create a route in routes.rb:
match '/othermap' => 'foo#othermap'
Then in foo_controller.rb:
def othermap
#kmlurl = "http://mysite/file2.kml"
end
Then create othermap.js.erb:
$('#ajax_map').html(
'<%=
escape_javascript(
gmaps( :kml => { :data => "[{ url: #{#kmlurl}}]" } )
)
%>'
)
That's a quick fix, but what I would REALLY do is strive to make your view code as simple as possible, and do all the real work in the controller. Ideally your view would just be:
<div id="ajax_map">
<%= gmaps( :kml => { :data => #mapdata } ) %>
</div>
set up #mapdata as appropriate in your controller. You've got too much stuff that really belongs in a controller embedded in your view code! Your othermap.js.erb should be equally simplified. i.e.
$('#ajax_map').html('<%= escape_javascript(gmaps( :kml => { :data => #mapdata } ))%>')

Using ajax pagination (will_paginate) for multiple groups of the same model

I have gotten ajax pagination working using mislav-will_paginate with the js found here: https://github.com/mislav/will_paginate/wiki/Ajax-pagination but I have run into a situation that I am not sure how to handle. I have a number of groups (of the same model) and each group has a number of lists that are paginated. I cannot tell which group to load the lists for in the ajax pagination call. This is the code I am using:
function ajaxPagination(){
var container = $(document.body)
if (container) {
container.observe('click', function(e) {
var el = e.element();
if (el.match('.pagination a')) {
new Ajax.Request(el.href, { method: 'get' })
e.stop()
}
})
}
}
<% #groups.each do |group| %>
<% lists = group.lists.paginate(:page => params[:group_page], :per_page => 5) %>
<% lists.each .... %>
<%= will_paginate lists, :params_name => "group_page" %>
<% end %>
You need to improve your JS to know which 'group' you're clicking.
$("#<%= group %>").html("<%= escape_javascript(render("group")) %>");
See: http://railscasts.com/episodes/174-pagination-with-ajax or read it at: http://asciicasts.com/episodes/174-pagination-with-ajax
$('.group').click(function(){
$.ajax({
type: "GET",
url: "/group",
data: { 'group' : $(this).attr('id') }
success: function(data){
alert( "Success" );
}
});
});

How can you go to the next record set when clicking an image using will_paginate

I am using rails 3 and will_paginate to browse through photos. I have it working except I would also like it so that users can view the next record by clicking the picture rather than the next button in the pagination navigation. Very similar to facebooks image viewing or something like the following: http://exposure.blogocracy.org/demos/demo1.html
I don't know if will_paginate has any parameters to allow this to work... any help or direction would be very much appreciated
controller - image - action: gallery
def gallery
#images = Image.all.paginate(:per_page => 1, :page => params[:page])
end
view image - gallery
<div id="slideshow">
<% #images.each do |image| %>
<%= image_tag("gallery/"+image.path, :alt => "") %>
<% end %>
</div>
view layout - _nav
<%= will_paginate #images, :previous_label => '« ',
:next_label => '»',
:params => { :controller => "images",
:action => "gallery" },
:separator => ' ',
:inner_window => 4,
:outer_window => -1 %>
-----------EDIT--------------
As a work around I decided to use javascript / jquery and link it manual.. it's really really ugly but im using it until i figure out the right way to do it.
`
$(document).ready(function() {
$('div#slideshow img').live('click', function() {
var has_images = '<%= #has_image %>';
if( has_images == 1 ) {
var page = '<%= #next_image.id %>';
var url = '/images/gallery?page='+page
window.location.replace(url);
}
else {
var url = '/images/gallery?page=1'
window.location.replace(url);
}
})
})
`
The example you are linking to is a jQuery plugin called Exposure why don't you just use that?
And i wouldn't recommend Will_paginate for that you want.
Oluf Nielsen

Resources