无法访问来自 Jquery 的关联模型
Can not reach to associated models from Jquery
我有关联的模型。船和位置模型。我正在尝试从 Jquery 代码访问 Boat Model,但我做不到。事情;我 return Jquery 的所有位置作为 listing
并且它包含地址,boat_id 等。所以 listing.address
有效,listing.boat_id
有效但 listing.boat.year
(例如)不起作用。它给出了一个错误; Boat 未定义,因为它不是 rails 代码,对吧?。但是我找不到通过它的方法。它应该像 <%= listing.Boat.model %>
.
我想知道可能是因为js函数使用了parse.HTML
。这是将给定列表插入 dom;
的函数
/*
*Insert given listings to the dom
*/
function insert_listing( index , listing ){
//create html for each listing using listing template function (options), and attach hover event listener which highlights the
//related marker when the listing is hovered (BECAUSE OF HERE??)
var html = $($.parseHTML(settings.listing_template( listing ))).wrap( settings.listing_wrapper ).parent().attr( 'data-mid' ,
index ).addClass( settings.listing_class ).mouseenter( function(){
var mid = $(this).attr('data-mid');
$.each(markers , function( index , marker ){
if( Number(marker.get('mid')) === Number( mid) ){
marker.setIcon( settings.highlighted_icon );
}
})
}).mouseleave(function(){
var mid = $(this).attr('data-mid');
$.each(markers , function(index , marker){
if(Number(marker.get('mid')) === Number( mid)){
marker.setIcon( settings.icon );
}
})
});
$(settings.listings_el).append( html );
}
这是协会;
船 has_one :location
位置 belongs_to :boat
这是 html.erb 文件中的 jquery
<script>
(function ( $ ) {
$('#map-canvas').mapSearch({
request_uri: 'locations/show.json',
initialPosition: [ <%= @initlat %> , <%= @initlng %> ], #THIS WORKS
filters_form : '#filters',
listing_template : function(listing){
return '<div class="listing">'
+ '<h3>'+listing.address + '</h3>'
//<%= listing.Boat.model %> DOES NOT WORK
//<%= listing.boat.model %> DOES NOT WORK
+ '<div class="row">'
+ '<div class="col-sm-2">'
+ '<img class="thumbnail img-responsive" src="http://dummyimage.com/150x150/000/fff.jpg">'
+ '</div>'
+ '<div class="col-sm-5">'
+ '<p><strong>Address : </strong>' + listing.address+ '</p>'
+ '<p>'+listing.address+', '+listing.address+' '+listing.address+'</p>'
+ '<p>Reg Year: ' + listing.address+'</p>'
+ '</div>'
+ '<div class="col-sm-5">'
+ '<p><strong>Demo</strong> '+listing.address+'</p>'
+ '<p><strong>Demo</strong> '+listing.address+'</p>'
+ '</div>'
+ '</div>'
+ '</div>';
},
marker_clusterer : true
});
}( jQuery ));
</script>
我不知道与此相关的是 locations_controller,它将数据发送到 jquery;
class LocationsController < ApplicationController
def index
if params[:search].present?
location = Geocoder.search(params[:search])
@locations =location[0]
else
@locations = Location.all.first
end
@initlat = @locations.latitude
@initlng = @locations.longitude
end
def show
#I ll process these later
ne_lat = params[:ne_lat].to_f
ne_lng = params[:ne_lng].to_f
sw_lat = params[:sw_lat].to_f
sw_lng = params[:sw_lng].to_f
mylatlong2 = Location.all
locs = {'results' => mylatlong2}
respond_to do |format|
format.html
format.json {render json: locs}
end
end
end
所以实际上在 rails 控制台中,例如 Location.last.Boat.year
有效。谢谢您的帮助。我很感激!
PS: 这是我从 get request (controller) 得到的;
{"results":[{"id":15,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.874432,"latitude":40.971388,"location_type":null,"boat_id":250,"created_at":"2015-05-17T11:36:29.245Z","updated_at":"2015-05-17T11:36:29.245Z","distance":0.060815068242947884,"bearing":135.0},{"id":16,"address":"Ataköy Marina, İstanbul, Türkiye","longitude":28.874432,"latitude":40.971388,"location_type":null,"boat_id":251,"created_at":"2015-05-21T21:27:43.366Z","updated_at":"2015-05-21T21:27:43.366Z","distance":0.060815068242947884,"bearing":135.0},{"id":1,"address":null,"longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":null,"created_at":"2015-05-12T08:01:08.899Z","updated_at":"2015-05-12T08:01:19.769Z","distance":0.06081506824595426,"bearing":135.0},{"id":2,"address":null,"longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":null,"created_at":"2015-05-12T08:01:26.659Z","updated_at":"2015-05-12T08:02:14.615Z","distance":0.06081506824595426,"bearing":135.0},{"id":3,"address":null,"longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":null,"created_at":"2015-05-12T08:02:32.089Z","updated_at":"2015-05-12T08:03:11.074Z","distance":0.06081506824595426,"bearing":135.0},{"id":4,"address":null,"longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":null,"created_at":"2015-05-12T08:03:14.706Z","updated_at":"2015-05-12T08:03:50.343Z","distance":0.06081506824595426,"bearing":135.0},{"id":5,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":242,"created_at":"2015-05-12T08:03:56.194Z","updated_at":"2015-05-12T08:03:56.194Z","distance":0.06081506824595426,"bearing":135.0},{"id":6,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":243,"created_at":"2015-05-12T08:07:03.799Z","updated_at":"2015-05-12T08:07:03.799Z","distance":0.06081506824595426,"bearing":135.0},{"id":7,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":244,"created_at":"2015-05-12T08:08:25.252Z","updated_at":"2015-05-12T08:08:25.252Z","distance":0.06081506824595426,"bearing":135.0},{"id":8,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":245,"created_at":"2015-05-12T08:20:38.188Z","updated_at":"2015-05-12T08:20:38.188Z","distance":0.06081506824595426,"bearing":135.0},{"id":9,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":246,"created_at":"2015-05-12T08:21:34.724Z","updated_at":"2015-05-12T08:21:34.724Z","distance":0.06081506824595426,"bearing":135.0},{"id":10,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":247,"created_at":"2015-05-12T08:22:49.400Z","updated_at":"2015-05-12T08:22:49.400Z","distance":0.06081506824595426,"bearing":135.0},{"id":11,"address":"Fenerbahçe Yat Limanı, Kadıköy, Türkiye","longitude":29.037873999999988,"latitude":40.970286,"location_type":null,"boat_id":248,"created_at":"2015-05-12T08:23:43.187Z","updated_at":"2015-05-12T08:23:43.187Z","distance":7.03002425919155,"bearing":135.0},{"id":13,"address":"Fenerbahçe Yat Limanı, Kadıköy, Türkiye","longitude":29.037874,"latitude":40.970286,"location_type":null,"boat_id":249,"created_at":"2015-05-12T14:59:01.117Z","updated_at":"2015-05-12T14:59:01.117Z","distance":7.030024259192001,"bearing":135.0},{"id":14,"address":"Fenerbahçe Yat Limanı, Kadıköy, Türkiye","longitude":29.037874,"latitude":40.970286,"location_type":null,"boat_id":null,"created_at":"2015-05-17T11:36:03.798Z","updated_at":"2015-05-17T11:36:05.476Z","distance":7.030024259192001,"bearing":135.0}]}
并且 js 代码将其作为列表获取。所以我认为; <%= listing.boat.model %>
应该可以,但会报错;
NameError in LocationsController#index
undefined local variable or method 'listing' for #<#<Class:0x007f9665a25758>:0x007f96658c93a0>
编辑 1:
这是完整的js文件;
(function ( $ , window , undefined) {
$.fn.mapSearch = function ( options ) {
var el , settings , markers = [] , params , extra_params = [] , marker , markerClusterer, mapOptions , map , infowindow;
el = this[0];
/*
*Default settings for the plugin.
*/
settings = $.extend({
/*
*Number: Initial zoom level of the map.
*/
zoom: 6,
/*
*Array: Initial position coordinates of the map [latitude , longitude].
*/
initialPosition: [40, -100],
/*
*String: URL where the plugin will make ajaz request for json data
*/
request_uri : '',
/*
*String: ID of the element you want to insert listings in
*/
listings_el : '#ms-listings',
/*
*String: ID of the element you want to insert pagination in
*/
pagination_el : '#ms-pagination',
/*
*Function: Template function that receives a listing as parameter and returns HTML for it
*/
listing_template : function(listing){
return '<div class="listing">'
+ '<h3>'+listing.name + '</h3>'
+ '<p><strong>Address : </strong>' + listing.address+ '</p>'
+ '<p><strong>Women owned:</strong> '+listing.women+'</p>'
+ '<p><strong>Accept Govt Credit card:</strong> '+listing.gcc+'</p>'
+ '</div>';
},
/*
*String: Wrapper around each listing
*/
listing_wrapper : '<div></div>',
/*
*Function: Receives entire response as parameter and returns page number identifier in the response
*/
page_number : function(data){
return 3/*data.meta.page BURASI DEĞİŞECEK!!!!!!*/;
},
/*
*Function: Receives a listing as parameter and returns an array of latitude and longitude pair
*/
listing_latlng: function(listing){
return [listing.latitude , listing.longitude];
},
/*
*Function: Receives a listing as parameter and returns Content for infowindow of each marker
*/
infowindow_content : function(listing){
return '<div>' + listing.name + '<div>';
},
/*
*String : Class to be added to map container
*/
map_class : 'ms-map',
/*
*String : Class to be added to listings container
*/
listings_class : 'ms-results',
/*
*String : Class to be added to single listing container
*/
listing_class : 'ms-listing',
/*
*String : Class to be added to pagination links
*/
pagi_link_class : 'ms-pagination-button',
/*
*String : Text that appears on link to next page
*/
next_btn_text : 'Next',
/*
*String : Text that appears on link to previous page
*/
prev_btn_text : 'Previous',
/*
*String : Class to be added to show loading indicator
*/
loading_class : 'loading',
/*
*String : Path to marker icon to be used for each listing
*/
icon : "<%= asset_path 'normal.png' %>", //Icon to be used on map
/*
*String : Path to highlighted marker icon to be used for each listing
*/
highlighted_icon : "<%= asset_path 'highlight.png' %>",
/*
*String : Identifier of the listings array in response data
*/
results_key : 'results',
/*
*Boolean : False for no filters, form ID for using filters
*/
filters_form : false,
/*
*Boolean : To enable marker clusters, set this to true, otherwise false
*/
marker_clusterer : false,
/*
*Boolean : To enable search box, set this to true, otherwise false
*/
search_box : true,
/*
*String : Class to be added to search box
*/
searchbox_class : 'form-control',
searchbox_placeholder : 'Search for a location',
}, options );
/*
*Adding Plugin Classes
*/
$( settings.listings_el ).addClass( settings.listings_class );
$( el ).addClass( settings.map_class );
/*
*Initializing the map
*/
mapOptions = {
center: new google.maps.LatLng( settings.initialPosition[0] , settings.initialPosition[1] ),
zoom: settings.zoom,
streetViewControl: false,
panControl: true,
panControlOptions: {
position: google.maps.ControlPosition.RIGHT_BOTTOM
},
zoomControlOptions: {
style: google.maps.ZoomControlStyle.LARGE,
position: google.maps.ControlPosition.LEFT_BOTTOM
},
};
map = new google.maps.Map( el, mapOptions );
/*
*Add searchbox if enabled in options
*/
if( settings.search_box ){
if(typeof google.maps.places === "object"){
$( el ).prepend( '<input style="top:25px !important;" type="text" id="search-form">' );
var input = (document.getElementById('search-form'));
$('#search-form').addClass( settings.searchbox_class ).prop('placeholder' , settings.searchbox_placeholder);
map.controls[google.maps.ControlPosition.TOP_CENTER].push(input);
var searchBox = new google.maps.places.SearchBox(input);
google.maps.event.addListener(searchBox, 'places_changed', function() {
var place = searchBox.getPlaces();
if(place.length > 0){
map.panTo(place[0].geometry.location);
}
});
}else{
alert('Google Places library not found')
}
}
/*
*Initializing the InfoWindow for markers
*/
infowindow = new google.maps.InfoWindow();
/*
*Initializing clusterer if needed
*/
if(settings.marker_clusterer && typeof MarkerClusterer === 'function'){
markerClusterer = new MarkerClusterer(map, markers, {gridSize: 50, maxZoom: 15});
}
/*
*Adding an event listener for every time the user moves or zooms the map, we refresh the listings search
*/
new google.maps.event.addListener( map , 'idle' , function(){
params = get_bounds();
request_listings( extra_params );
});
/*
*Utility function: To get the bounds of the map
*/
function get_bounds(){
return {
sw_lat : map.getBounds().getSouthWest().lat(),
sw_lng : map.getBounds().getSouthWest().lng(),
ne_lat : map.getBounds().getNorthEast().lat(),
ne_lng : map.getBounds().getNorthEast().lng()
};
}
/*
*Function to make an ajax request to server for data
*Most of the other functions are called inside this one.
*/
function request_listings( new_params ){
//checking if the request url is provided
if(settings.request_uri != ''){
//Add loading indicator class
$(el).addClass( settings.loading_class );
$(settings.listings_el).addClass( settings.loading_class );
//make the ajax request with all the parameters as get variables
$.get(settings.request_uri+ '?' + $.param( $.extend(params , new_params) ), function(data){
//deleting old markers
deleteMarkers();
//removing old listings
$(settings.listings_el).empty();
//processing the returned data. Adding listings to the page and create markers
$.each(data[ settings.results_key ] , function( index , value ){
insert_listing( index , value );
addMarker( index , value );
});
//remove the previous pagination and add new one
$(settings.pagination_el).empty().prepend(create_pagination(settings.page_number(data)));
//bind click events to pagination buttons
$('.'+settings.pagi_link_class).click(function(){
extra_params['page'] = $(this).data('href');
$.fn.mapSearch.update(extra_params);
});
//add markers to the map
if(settings.marker_clusterer && typeof MarkerClusterer === 'function'){
markerClusterer.clearMarkers();
markerClusterer.addMarkers(markers);
}else{
showMarkers();
}
//remove loading class
$(el).removeClass( settings.loading_class );
$(settings.listings_el).removeClass( settings.loading_class );
});
}
}
//Handle the filters form.
processFilters();
/*
*Attach the infowindow created previously to a marker that is clicked, receives a mcontent string and marker as parameter
*/
function makeInfoWindowEvent( contentString, marker ) {
google.maps.event.addListener( marker, 'click', function() {
infowindow.setContent( contentString );
infowindow.open( map, marker );
});
}
/*
*Creates a marker from given listing and adds to the markers array
*/
function addMarker( index , listing ) {
var latlng = settings.listing_latlng( listing );
var marker = new google.maps.Marker({
position: new google.maps.LatLng( latlng[0], latlng[1] ),
title : listing.name,
mid : index,
icon : settings.icon,
});
if(!settings.marker_clusterer){
marker.setMap(map);
}
//Attach infowindow event to the marker
makeInfoWindowEvent(settings.infowindow_content( listing ), marker );
//add to array
markers.push(marker);
}
//Set markers on the map
function setAllMap(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
//Remove markers from map
function clearMarkers() {
setAllMap(null);
}
//Show all markers present in array
function showMarkers() {
setAllMap(map);
}
/*
*Function : Receives current page number as parameter, returns HTML for pagination
*/
function create_pagination(page_number){
var prev = page_number > 1 ? '<li><a href="#" class="'+ settings.pagi_link_class +'" data-href="'+ (page_number - 1) +'">'+ settings.prev_btn_text +'</a></li>' : '';
var next = '<li><a href="#" class="'+ settings.pagi_link_class +'" data-href="'+ (page_number + 1) +'">' + settings.next_btn_text + '</a></li>';
return $(prev + next).wrapAll('<ul></ul>').parent().addClass('pagination');
}
/*
*Attach an event listener to filters form
*Whenever form values are changed, update the map and listings
*/
function processFilters(){
if(settings.filters_form != false && typeof settings.filters_form === 'string'){
$(settings.filters_form + ' :input').change(function(){
var filters = $(settings.filters_form).serializeArray();
var params = [];
for(var i in filters){
params[filters[i].name] = filters[i].value;
}
$.fn.mapSearch.update(params);
});
}
}
/*
*Delete all markers from array
*/
function deleteMarkers() {
clearMarkers();
markers = [];
}
/*
*Insert given listings to the dom
*/
function insert_listing( index , listing ){
//create html for each listing using listing template function (options), and attach hover event listener which highlights the
//related marker when the listing is hovered
var html = $($.parseHTML(settings.listing_template( listing ))).wrap( settings.listing_wrapper ).parent().attr( 'data-mid' ,
index ).addClass( settings.listing_class ).mouseenter( function(){
var mid = $(this).attr('data-mid');
$.each(markers , function( index , marker ){
if( Number(marker.get('mid')) === Number( mid) ){
marker.setIcon( settings.highlighted_icon );
}
})
}).mouseleave(function(){
var mid = $(this).attr('data-mid');
$.each(markers , function(index , marker){
if(Number(marker.get('mid')) === Number( mid)){
marker.setIcon( settings.icon );
}
})
});
$(settings.listings_el).append( html );
}
/*
*A utility method for updating the map with some new parameters
*/
$.fn.mapSearch.update = function(new_params){
extra_params = new_params;
params = get_bounds();
request_listings( extra_params );
delete extra_params['page'];
}
}
})( jQuery );
您很可能试图在 ruby 中使用 javascript 变量。
这种混淆是避免混合客户端和服务器端代码的众多原因之一。
相反,您可以使用数据属性和 ajax 将数据传递给 javascript。
<div id="map-canvas" data-initlat="<%= @initlat %>"></div>
或者另一个例子:
<body data-assets-path="<%= assets_path %>">.
在您的情况下,您需要确保 request_listings
调用的任何操作都提供呈现列表所需的 JSON 数据。
我有关联的模型。船和位置模型。我正在尝试从 Jquery 代码访问 Boat Model,但我做不到。事情;我 return Jquery 的所有位置作为 listing
并且它包含地址,boat_id 等。所以 listing.address
有效,listing.boat_id
有效但 listing.boat.year
(例如)不起作用。它给出了一个错误; Boat 未定义,因为它不是 rails 代码,对吧?。但是我找不到通过它的方法。它应该像 <%= listing.Boat.model %>
.
我想知道可能是因为js函数使用了parse.HTML
。这是将给定列表插入 dom;
/*
*Insert given listings to the dom
*/
function insert_listing( index , listing ){
//create html for each listing using listing template function (options), and attach hover event listener which highlights the
//related marker when the listing is hovered (BECAUSE OF HERE??)
var html = $($.parseHTML(settings.listing_template( listing ))).wrap( settings.listing_wrapper ).parent().attr( 'data-mid' ,
index ).addClass( settings.listing_class ).mouseenter( function(){
var mid = $(this).attr('data-mid');
$.each(markers , function( index , marker ){
if( Number(marker.get('mid')) === Number( mid) ){
marker.setIcon( settings.highlighted_icon );
}
})
}).mouseleave(function(){
var mid = $(this).attr('data-mid');
$.each(markers , function(index , marker){
if(Number(marker.get('mid')) === Number( mid)){
marker.setIcon( settings.icon );
}
})
});
$(settings.listings_el).append( html );
}
这是协会;
船 has_one :location
位置 belongs_to :boat
这是 html.erb 文件中的 jquery
<script>
(function ( $ ) {
$('#map-canvas').mapSearch({
request_uri: 'locations/show.json',
initialPosition: [ <%= @initlat %> , <%= @initlng %> ], #THIS WORKS
filters_form : '#filters',
listing_template : function(listing){
return '<div class="listing">'
+ '<h3>'+listing.address + '</h3>'
//<%= listing.Boat.model %> DOES NOT WORK
//<%= listing.boat.model %> DOES NOT WORK
+ '<div class="row">'
+ '<div class="col-sm-2">'
+ '<img class="thumbnail img-responsive" src="http://dummyimage.com/150x150/000/fff.jpg">'
+ '</div>'
+ '<div class="col-sm-5">'
+ '<p><strong>Address : </strong>' + listing.address+ '</p>'
+ '<p>'+listing.address+', '+listing.address+' '+listing.address+'</p>'
+ '<p>Reg Year: ' + listing.address+'</p>'
+ '</div>'
+ '<div class="col-sm-5">'
+ '<p><strong>Demo</strong> '+listing.address+'</p>'
+ '<p><strong>Demo</strong> '+listing.address+'</p>'
+ '</div>'
+ '</div>'
+ '</div>';
},
marker_clusterer : true
});
}( jQuery ));
</script>
我不知道与此相关的是 locations_controller,它将数据发送到 jquery;
class LocationsController < ApplicationController
def index
if params[:search].present?
location = Geocoder.search(params[:search])
@locations =location[0]
else
@locations = Location.all.first
end
@initlat = @locations.latitude
@initlng = @locations.longitude
end
def show
#I ll process these later
ne_lat = params[:ne_lat].to_f
ne_lng = params[:ne_lng].to_f
sw_lat = params[:sw_lat].to_f
sw_lng = params[:sw_lng].to_f
mylatlong2 = Location.all
locs = {'results' => mylatlong2}
respond_to do |format|
format.html
format.json {render json: locs}
end
end
end
所以实际上在 rails 控制台中,例如 Location.last.Boat.year
有效。谢谢您的帮助。我很感激!
PS: 这是我从 get request (controller) 得到的;
{"results":[{"id":15,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.874432,"latitude":40.971388,"location_type":null,"boat_id":250,"created_at":"2015-05-17T11:36:29.245Z","updated_at":"2015-05-17T11:36:29.245Z","distance":0.060815068242947884,"bearing":135.0},{"id":16,"address":"Ataköy Marina, İstanbul, Türkiye","longitude":28.874432,"latitude":40.971388,"location_type":null,"boat_id":251,"created_at":"2015-05-21T21:27:43.366Z","updated_at":"2015-05-21T21:27:43.366Z","distance":0.060815068242947884,"bearing":135.0},{"id":1,"address":null,"longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":null,"created_at":"2015-05-12T08:01:08.899Z","updated_at":"2015-05-12T08:01:19.769Z","distance":0.06081506824595426,"bearing":135.0},{"id":2,"address":null,"longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":null,"created_at":"2015-05-12T08:01:26.659Z","updated_at":"2015-05-12T08:02:14.615Z","distance":0.06081506824595426,"bearing":135.0},{"id":3,"address":null,"longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":null,"created_at":"2015-05-12T08:02:32.089Z","updated_at":"2015-05-12T08:03:11.074Z","distance":0.06081506824595426,"bearing":135.0},{"id":4,"address":null,"longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":null,"created_at":"2015-05-12T08:03:14.706Z","updated_at":"2015-05-12T08:03:50.343Z","distance":0.06081506824595426,"bearing":135.0},{"id":5,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":242,"created_at":"2015-05-12T08:03:56.194Z","updated_at":"2015-05-12T08:03:56.194Z","distance":0.06081506824595426,"bearing":135.0},{"id":6,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":243,"created_at":"2015-05-12T08:07:03.799Z","updated_at":"2015-05-12T08:07:03.799Z","distance":0.06081506824595426,"bearing":135.0},{"id":7,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":244,"created_at":"2015-05-12T08:08:25.252Z","updated_at":"2015-05-12T08:08:25.252Z","distance":0.06081506824595426,"bearing":135.0},{"id":8,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":245,"created_at":"2015-05-12T08:20:38.188Z","updated_at":"2015-05-12T08:20:38.188Z","distance":0.06081506824595426,"bearing":135.0},{"id":9,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":246,"created_at":"2015-05-12T08:21:34.724Z","updated_at":"2015-05-12T08:21:34.724Z","distance":0.06081506824595426,"bearing":135.0},{"id":10,"address":"Ataköy Marina, 34140, Bakırköy, İstanbul, Türkiye","longitude":28.87443200000007,"latitude":40.971388,"location_type":null,"boat_id":247,"created_at":"2015-05-12T08:22:49.400Z","updated_at":"2015-05-12T08:22:49.400Z","distance":0.06081506824595426,"bearing":135.0},{"id":11,"address":"Fenerbahçe Yat Limanı, Kadıköy, Türkiye","longitude":29.037873999999988,"latitude":40.970286,"location_type":null,"boat_id":248,"created_at":"2015-05-12T08:23:43.187Z","updated_at":"2015-05-12T08:23:43.187Z","distance":7.03002425919155,"bearing":135.0},{"id":13,"address":"Fenerbahçe Yat Limanı, Kadıköy, Türkiye","longitude":29.037874,"latitude":40.970286,"location_type":null,"boat_id":249,"created_at":"2015-05-12T14:59:01.117Z","updated_at":"2015-05-12T14:59:01.117Z","distance":7.030024259192001,"bearing":135.0},{"id":14,"address":"Fenerbahçe Yat Limanı, Kadıköy, Türkiye","longitude":29.037874,"latitude":40.970286,"location_type":null,"boat_id":null,"created_at":"2015-05-17T11:36:03.798Z","updated_at":"2015-05-17T11:36:05.476Z","distance":7.030024259192001,"bearing":135.0}]}
并且 js 代码将其作为列表获取。所以我认为; <%= listing.boat.model %>
应该可以,但会报错;
NameError in LocationsController#index
undefined local variable or method 'listing' for #<#<Class:0x007f9665a25758>:0x007f96658c93a0>
编辑 1:
这是完整的js文件;
(function ( $ , window , undefined) {
$.fn.mapSearch = function ( options ) {
var el , settings , markers = [] , params , extra_params = [] , marker , markerClusterer, mapOptions , map , infowindow;
el = this[0];
/*
*Default settings for the plugin.
*/
settings = $.extend({
/*
*Number: Initial zoom level of the map.
*/
zoom: 6,
/*
*Array: Initial position coordinates of the map [latitude , longitude].
*/
initialPosition: [40, -100],
/*
*String: URL where the plugin will make ajaz request for json data
*/
request_uri : '',
/*
*String: ID of the element you want to insert listings in
*/
listings_el : '#ms-listings',
/*
*String: ID of the element you want to insert pagination in
*/
pagination_el : '#ms-pagination',
/*
*Function: Template function that receives a listing as parameter and returns HTML for it
*/
listing_template : function(listing){
return '<div class="listing">'
+ '<h3>'+listing.name + '</h3>'
+ '<p><strong>Address : </strong>' + listing.address+ '</p>'
+ '<p><strong>Women owned:</strong> '+listing.women+'</p>'
+ '<p><strong>Accept Govt Credit card:</strong> '+listing.gcc+'</p>'
+ '</div>';
},
/*
*String: Wrapper around each listing
*/
listing_wrapper : '<div></div>',
/*
*Function: Receives entire response as parameter and returns page number identifier in the response
*/
page_number : function(data){
return 3/*data.meta.page BURASI DEĞİŞECEK!!!!!!*/;
},
/*
*Function: Receives a listing as parameter and returns an array of latitude and longitude pair
*/
listing_latlng: function(listing){
return [listing.latitude , listing.longitude];
},
/*
*Function: Receives a listing as parameter and returns Content for infowindow of each marker
*/
infowindow_content : function(listing){
return '<div>' + listing.name + '<div>';
},
/*
*String : Class to be added to map container
*/
map_class : 'ms-map',
/*
*String : Class to be added to listings container
*/
listings_class : 'ms-results',
/*
*String : Class to be added to single listing container
*/
listing_class : 'ms-listing',
/*
*String : Class to be added to pagination links
*/
pagi_link_class : 'ms-pagination-button',
/*
*String : Text that appears on link to next page
*/
next_btn_text : 'Next',
/*
*String : Text that appears on link to previous page
*/
prev_btn_text : 'Previous',
/*
*String : Class to be added to show loading indicator
*/
loading_class : 'loading',
/*
*String : Path to marker icon to be used for each listing
*/
icon : "<%= asset_path 'normal.png' %>", //Icon to be used on map
/*
*String : Path to highlighted marker icon to be used for each listing
*/
highlighted_icon : "<%= asset_path 'highlight.png' %>",
/*
*String : Identifier of the listings array in response data
*/
results_key : 'results',
/*
*Boolean : False for no filters, form ID for using filters
*/
filters_form : false,
/*
*Boolean : To enable marker clusters, set this to true, otherwise false
*/
marker_clusterer : false,
/*
*Boolean : To enable search box, set this to true, otherwise false
*/
search_box : true,
/*
*String : Class to be added to search box
*/
searchbox_class : 'form-control',
searchbox_placeholder : 'Search for a location',
}, options );
/*
*Adding Plugin Classes
*/
$( settings.listings_el ).addClass( settings.listings_class );
$( el ).addClass( settings.map_class );
/*
*Initializing the map
*/
mapOptions = {
center: new google.maps.LatLng( settings.initialPosition[0] , settings.initialPosition[1] ),
zoom: settings.zoom,
streetViewControl: false,
panControl: true,
panControlOptions: {
position: google.maps.ControlPosition.RIGHT_BOTTOM
},
zoomControlOptions: {
style: google.maps.ZoomControlStyle.LARGE,
position: google.maps.ControlPosition.LEFT_BOTTOM
},
};
map = new google.maps.Map( el, mapOptions );
/*
*Add searchbox if enabled in options
*/
if( settings.search_box ){
if(typeof google.maps.places === "object"){
$( el ).prepend( '<input style="top:25px !important;" type="text" id="search-form">' );
var input = (document.getElementById('search-form'));
$('#search-form').addClass( settings.searchbox_class ).prop('placeholder' , settings.searchbox_placeholder);
map.controls[google.maps.ControlPosition.TOP_CENTER].push(input);
var searchBox = new google.maps.places.SearchBox(input);
google.maps.event.addListener(searchBox, 'places_changed', function() {
var place = searchBox.getPlaces();
if(place.length > 0){
map.panTo(place[0].geometry.location);
}
});
}else{
alert('Google Places library not found')
}
}
/*
*Initializing the InfoWindow for markers
*/
infowindow = new google.maps.InfoWindow();
/*
*Initializing clusterer if needed
*/
if(settings.marker_clusterer && typeof MarkerClusterer === 'function'){
markerClusterer = new MarkerClusterer(map, markers, {gridSize: 50, maxZoom: 15});
}
/*
*Adding an event listener for every time the user moves or zooms the map, we refresh the listings search
*/
new google.maps.event.addListener( map , 'idle' , function(){
params = get_bounds();
request_listings( extra_params );
});
/*
*Utility function: To get the bounds of the map
*/
function get_bounds(){
return {
sw_lat : map.getBounds().getSouthWest().lat(),
sw_lng : map.getBounds().getSouthWest().lng(),
ne_lat : map.getBounds().getNorthEast().lat(),
ne_lng : map.getBounds().getNorthEast().lng()
};
}
/*
*Function to make an ajax request to server for data
*Most of the other functions are called inside this one.
*/
function request_listings( new_params ){
//checking if the request url is provided
if(settings.request_uri != ''){
//Add loading indicator class
$(el).addClass( settings.loading_class );
$(settings.listings_el).addClass( settings.loading_class );
//make the ajax request with all the parameters as get variables
$.get(settings.request_uri+ '?' + $.param( $.extend(params , new_params) ), function(data){
//deleting old markers
deleteMarkers();
//removing old listings
$(settings.listings_el).empty();
//processing the returned data. Adding listings to the page and create markers
$.each(data[ settings.results_key ] , function( index , value ){
insert_listing( index , value );
addMarker( index , value );
});
//remove the previous pagination and add new one
$(settings.pagination_el).empty().prepend(create_pagination(settings.page_number(data)));
//bind click events to pagination buttons
$('.'+settings.pagi_link_class).click(function(){
extra_params['page'] = $(this).data('href');
$.fn.mapSearch.update(extra_params);
});
//add markers to the map
if(settings.marker_clusterer && typeof MarkerClusterer === 'function'){
markerClusterer.clearMarkers();
markerClusterer.addMarkers(markers);
}else{
showMarkers();
}
//remove loading class
$(el).removeClass( settings.loading_class );
$(settings.listings_el).removeClass( settings.loading_class );
});
}
}
//Handle the filters form.
processFilters();
/*
*Attach the infowindow created previously to a marker that is clicked, receives a mcontent string and marker as parameter
*/
function makeInfoWindowEvent( contentString, marker ) {
google.maps.event.addListener( marker, 'click', function() {
infowindow.setContent( contentString );
infowindow.open( map, marker );
});
}
/*
*Creates a marker from given listing and adds to the markers array
*/
function addMarker( index , listing ) {
var latlng = settings.listing_latlng( listing );
var marker = new google.maps.Marker({
position: new google.maps.LatLng( latlng[0], latlng[1] ),
title : listing.name,
mid : index,
icon : settings.icon,
});
if(!settings.marker_clusterer){
marker.setMap(map);
}
//Attach infowindow event to the marker
makeInfoWindowEvent(settings.infowindow_content( listing ), marker );
//add to array
markers.push(marker);
}
//Set markers on the map
function setAllMap(map) {
for (var i = 0; i < markers.length; i++) {
markers[i].setMap(map);
}
}
//Remove markers from map
function clearMarkers() {
setAllMap(null);
}
//Show all markers present in array
function showMarkers() {
setAllMap(map);
}
/*
*Function : Receives current page number as parameter, returns HTML for pagination
*/
function create_pagination(page_number){
var prev = page_number > 1 ? '<li><a href="#" class="'+ settings.pagi_link_class +'" data-href="'+ (page_number - 1) +'">'+ settings.prev_btn_text +'</a></li>' : '';
var next = '<li><a href="#" class="'+ settings.pagi_link_class +'" data-href="'+ (page_number + 1) +'">' + settings.next_btn_text + '</a></li>';
return $(prev + next).wrapAll('<ul></ul>').parent().addClass('pagination');
}
/*
*Attach an event listener to filters form
*Whenever form values are changed, update the map and listings
*/
function processFilters(){
if(settings.filters_form != false && typeof settings.filters_form === 'string'){
$(settings.filters_form + ' :input').change(function(){
var filters = $(settings.filters_form).serializeArray();
var params = [];
for(var i in filters){
params[filters[i].name] = filters[i].value;
}
$.fn.mapSearch.update(params);
});
}
}
/*
*Delete all markers from array
*/
function deleteMarkers() {
clearMarkers();
markers = [];
}
/*
*Insert given listings to the dom
*/
function insert_listing( index , listing ){
//create html for each listing using listing template function (options), and attach hover event listener which highlights the
//related marker when the listing is hovered
var html = $($.parseHTML(settings.listing_template( listing ))).wrap( settings.listing_wrapper ).parent().attr( 'data-mid' ,
index ).addClass( settings.listing_class ).mouseenter( function(){
var mid = $(this).attr('data-mid');
$.each(markers , function( index , marker ){
if( Number(marker.get('mid')) === Number( mid) ){
marker.setIcon( settings.highlighted_icon );
}
})
}).mouseleave(function(){
var mid = $(this).attr('data-mid');
$.each(markers , function(index , marker){
if(Number(marker.get('mid')) === Number( mid)){
marker.setIcon( settings.icon );
}
})
});
$(settings.listings_el).append( html );
}
/*
*A utility method for updating the map with some new parameters
*/
$.fn.mapSearch.update = function(new_params){
extra_params = new_params;
params = get_bounds();
request_listings( extra_params );
delete extra_params['page'];
}
}
})( jQuery );
您很可能试图在 ruby 中使用 javascript 变量。
这种混淆是避免混合客户端和服务器端代码的众多原因之一。
相反,您可以使用数据属性和 ajax 将数据传递给 javascript。
<div id="map-canvas" data-initlat="<%= @initlat %>"></div>
或者另一个例子:
<body data-assets-path="<%= assets_path %>">.
在您的情况下,您需要确保 request_listings
调用的任何操作都提供呈现列表所需的 JSON 数据。