Gmaps4rails Polygon not displaying [duplicate] - ruby
Ruby noob here. Trying to display a list of points as a polygon on a google map using the gmaps4rails gem (awesome gem by the way). Any suggestions based on code sample below would be much appreciated! I can see the outline for the map, but no map and no polygon. Update: this code has been updated and the problem is solved.
Class Schoolpoint is a list of lat/long pairs that belong to School
In my controller:
#polyjson = []
schoolpoints = []
Schoolpoint.where(:school_id => params[:id]).each do |point|
schoolpoints << { :lng => point.longitude, :lat => point.latitude}
end
#polyjson = [schoolpoints]
#polyjson = #polyjson.to_json
Then in the view:
<%= gmaps({"polygons" => { "data" => #polyjson }})
in Schoolpoint model:
class Point < ActiveRecord::Base
belongs_to :place
acts_as_gmappable :process_geocoding => false
def gmaps4rails_address
"#{longitude}, #{latitude}"
end
end
Update: This error now longer exists, but I've left it in case its helpful to someone dealing with similar problem. Finally, here is the resulting js with an uncaught Syntaxerror => unexpected token.
Gmaps.map = new Gmaps4RailsGoogle();
Gmaps.load_map = function() {
Gmaps.map.initialize();
Gmaps.map.polygons = [[{"lng"=>-80.190262, "lat"=>25.774252, "strokeColor"=>"#FF0000", "strokeOpacity"=>0.3, "strokeWeight"=>1, "fillColor"=>"#FF0000", "fillOpacity"=>0.7}, {"lng"=>-87.6245284080505, "lat"=>41.8868315803506}, {"lng"=>-87.6241636276245, "lat"=>41.8674515900783}, {"lng"=>-87.6203870773315, "lat"=>41.8674835487326}, {"lng"=>-87.6167392730712, "lat"=>41.8579591627635}, {"lng"=>-87.6348495483398, "lat"=>41.8577034549953}, {"lng"=>-87.6342701911926, "lat"=>41.8588701133785}, {"lng"=>-87.6341199874878, "lat"=>41.858946025344}, {"lng"=>-87.6341146230697, "lat"=>41.8590858629394}, {"lng"=>-87.6341199874878, "lat"=>41.8600767034266}, {"lng"=>-87.6342219114303, "lat"=>41.8612433185139}, {"lng"=>-87.634157538414, "lat"=>41.8613112372298}, {"lng"=>-87.6342540979385, "lat"=>41.8621502271823}, {"lng"=>-87.6341950893402, "lat"=>41.8622580965204}, {"lng"=>-87.6342433691024, "lat"=>41.8626336402037}, {"lng"=>-87.6341092586517, "lat"=>41.8630930789441}, {"lng"=>-87.6342326402664, "lat"=>41.8631010691539}, {"lng"=>-87.6342862844467, "lat"=>41.8651984646832}, {"lng"=>-87.6342165470123, "lat"=>41.865314318812}, {"lng"=>-87.6342540979385, "lat"=>41.865929540668}, {"lng"=>-87.6343238353729, "lat"=>41.8661652409794}, {"lng"=>-87.6343667507171, "lat"=>41.8664728485533}, {"lng"=>-87.6342701911926, "lat"=>41.866564731048}, {"lng"=>-87.6343882083892, "lat"=>41.8673317449823}, {"lng"=>-87.6344525814056, "lat"=>41.8680388278011}, {"lng"=>-87.6346457004547, "lat"=>41.8691693450993}, {"lng"=>-87.6346671581268, "lat"=>41.8696886572982}, {"lng"=>-87.6345813274383, "lat"=>41.8698804022745}, {"lng"=>-87.6347583532333, "lat"=>41.869992253245}, {"lng"=>-87.634892463684, "lat"=>41.8706873227465}, {"lng"=>-87.6353269815445, "lat"=>41.8726167002032}, {"lng"=>-87.6352626085281, "lat"=>41.8728443868687}, {"lng"=>-87.6354557275772, "lat"=>41.8730081609862}, {"lng"=>-87.6353698968887, "lat"=>41.8732797854267}, {"lng"=>-87.6356971263885, "lat"=>41.8740227522642}, {"lng"=>-87.6356971263885, "lat"=>41.8746458790817}, {"lng"=>-87.6359224319458, "lat"=>41.87509724279}, {"lng"=>-87.6361316442489, "lat"=>41.8754088017203}, {"lng"=>-87.6364105939865, "lat"=>41.8754727110567}, {"lng"=>-87.6364642381668, "lat"=>41.8757642965932}, {"lng"=>-87.6371240615844, "lat"=>41.876678987795}, {"lng"=>-87.637939453125, "lat"=>41.8801059676767}, {"lng"=>-87.6379930973053, "lat"=>41.8806172030015}, {"lng"=>-87.6378536224365, "lat"=>41.8829017358812}, {"lng"=>-87.6375961303711, "lat"=>41.8844593251054}, {"lng"=>-87.6372849941253, "lat"=>41.8857213439117}, {"lng"=>-87.6371347904205, "lat"=>41.8860408383893}, {"lng"=>-87.6355576515197, "lat"=>41.8870552227663}, {"lng"=>-87.6282513141632, "lat"=>41.8870951588295}, {"lng"=>-87.6281654834747, "lat"=>41.8868076186168}]];
153:2439 Uncaught SyntaxError: Unexpected token >
Gmaps.map.create_polygons();
Gmaps.map.adjustMapToBounds();
Gmaps.map.callback();
};
window.onload = function() { Gmaps.loadMaps(); };
I passed their base tutorial (from screen cast) and markers works fine. But I had problem with polylines (as you with polygons). At the end I resolved my problem (it can help you with polygons).
So, view is the same as they gave :
<%= gmaps({
"polylines" => { "data" => #bemap_polylines }
})
%>
The model is also the same as their.
class Character < ActiveRecord::Base
belongs_to :bemap
acts_as_gmappable
def gmaps4rails_address
#describe how to retrieve the address from your model, if you use directly a db column, you can dry your code, see wiki
address
logger.info address
end
end
So, the main problem was into controller. Here is mine :
def show
#bemap = Bemap.find(params[:id])
#bemap_polylines = []
#bemap_characters = []
#bemap.characters.each do |v|
#bemap_characters << { :lng => v[:longitude], :lat => v[:latitude]}
end
#bemap_polylines << #bemap_characters
#bemap_polylines = #bemap_polylines.to_json
respond_to do |format|
format.html # show.html.erb
format.json { render json: #bemap }
end
end
Gmaps4rails doesn't provide any builtin method to create the js for polygons.
The one you use is malformed, see doc: https://github.com/apneadiving/Google-Maps-for-Rails/wiki/Polygons.
Related
Using current_user to customize ActionCable channel submittion
I'm making instant commenting with Rails 5. Using Rails *.js.erb, which is comfortable for this size of project. Also use ActionCable to deliver new comments to users. The thing is that I want ActionCable to send rendered comments/_comment.html.haml directly to client to evaluate this code in browser. In common case it's totally achivable. But in erb template of comment I have to deal with current_user to add delete link if current_user.admin? The problem is when I invoke CommentsChannel.broadcast_to and render _comment.html.haml renderer do not now current_user. Question is how can I render _comment.html.haml and submit it to each separate subscription defined by current user, using current user from this subscription? Devise is used for authentication. comments/_comment.html.haml %div[comment] .details %span.author= comment.user.email %span.time= l comment.created_at, format: :short = comment.body = link_to t('common.reply'), comment, class: 'reply-link' = link_to t('common.delete'), comment, method: :delete, remote: true if current_user.admin? = render 'comments/form', comment: comment.commentable.comment_threads.build, parent: comment - if comment.children.any? .child-comments = render comment.children.sort_by { |c| c.created_at }.reverse application_cable/connection.rb module ApplicationCable class Connection < ActionCable::Connection::Base identified_by :current_user def connect self.current_user = find_verified_user end def find_verified_user if verified_user = env['warden'].user verified_user else reject_unauthorized_connection end end end end broadcast_comment_job.rb class BroadcastCommentJob < ApplicationJob queue_as :default def perform(comment) CommentsChannel.broadcast_to \ comment.commentable, comment: render_comment(comment) end private def render_comment(comment) CommentsController.render(partial: 'comment', locals: { comment: comment }) end end comment.rb class Comment < ActiveRecord::Base ... after_create_commit { BroadcastCommentJob.perform_now(self) } ... end
using "AND" operator in rails
I have something like this: #photos = Photo.where(:user_id => #user.id) I want something like: #photos = Photo.where(:user_id => #user.id, :public => 1) However this does not work. I cannot find how to use the "AND" operator
Your solution should work: Photo.where(user_id: #user.id, public: 1) Generates a query like this (assuming MySQL and a #user.id of 5): SELECT `photos`.* FROM `photos` WHERE ((`photos`.`user_id` = 5 AND `photos`.`public` = 1)) I suspect that public is a boolean field and depending on your database adapter, true and false can either be stored as 1 and 0 or as t and f. Try to pass a boolean value instead and let Rails handle the conversion: Photo.where(user_id: #user.id, public: true) It's even easier if you set up associations and some scopes: class User < ActiveRecord::Base has_many :photos end class Photo < ActiveRecord::Base belongs_to :user scope :public, -> { where(public: true) } scope :private, -> { where(public: false) } end Now you can fetch a user's photos with: #user.photos.public # user's public photos #user.photos.private # user's private photos
Databases do not always store boolean values as 1 or 0. So ActiveRecord normalizes that and only recognizes true and false (or nil) when using hash conditions. All these queries are equivalent: #photos = Photo.where("user_id = ? AND public = ?", #user.id, 1) #photos = Photo.where(user_id: #user.id, public: true) #photos = Photo.where(user: #user, public: true) But it is generally preferred to write it like that: #photos = #user.photos.where(public: true)
Try #photos = Photo.where("user_id = ? AND public = ?", #user_id, 1) Active record documentation will help you.
Ruby Quick Class Instance Scope
I have a quick problem that probably comes down to something stupid. I have a class that extends OAuth::AccessToken and uses instance variables (#) so that each time it constructs an object, those variables will be unique that instance. However, when I try to return the final object from this class, I get an error. A quick example: require 'oauth' class OauthFigshare < OAuth::AccessToken def initialize (consumerkey, consumersecret, accesstoken, accesstokensecret) #consumerkey = consumerkey #consumersecret = consumersecret #accesstoken = accesstoken #accesstokensecret = accesstokensecret #apiurl = "http://api.figshare.com" #consumer = OAuth::Consumer.new(#consumerkey,#consumersecret,{:site=> #apiurl}) #token = { :oauth_token => #accesstoken, :oauth_token_secret => #accesstokensecret} puts #consumer.class puts #token #client = OAuth::AccessToken.from_hash(#consumer, #token) puts #client puts #client.get('/v1/my_data/articles') return #client end end The problem is that when I check inside the class to see if the token is working, it does. However, when I check against the constructed object outside the class, it doesn't work. #client.get(url) returns Net::HTTPOk calling from in the class auth = OauthFigshare.new(inputs) auth.get(url) This returns Net::HTTPUnauthorized What am I not getting about scope here? Edit to include actual class
The return value of the initialize method is not used. It seems like you actually want to override self.new instead.
Is there a better way to test this Ruby class with RSpec?
I'm extracting a subset of fields from a full JSON dataset having a JSON fixture. The better way I could think of is the following : require "spec_helper" # API ref.: GET /repos/:owner/:repo # http://developer.github.com/v3/repos/ describe Elasticrepo::RepoSubset do context "extract a subset of repository fields" do let(:parsed) { Yajl::Parser.parse(fixture("repository.json").read) } subject { Elasticrepo::RepoSubset.new(parsed) } context "#id" do its(:id) { should eq(2126244) } end context "#owner" do its(:owner) { should eq("twitter") } end context "#name" do its(:name) { should eq("bootstrap") } end context "#url" do its(:url) { should eq("https://api.github.com/repos/twitter/bootstrap") } end context "#description" do its(:description) { should eq("Sleek, intuitive, and powerful front-end framework for faster and easier web development.") } end context "#created_at" do its(:created_at) { should eq("2011-07-29T21:19:00Z") } end context "#pushed_at" do its(:pushed_at) { should eq("2013-04-13T03:56:36Z") } end context "#organization" do its(:organization) { should eq("Organization") } end context "#full_name" do its(:full_name) { should eq("twitter/bootstrap") } end context "#language" do its(:language) { should eq("JavaScript") } end context "#updated_at" do its(:updated_at) { should eq("2013-04-13T19:12:09Z") } end end end but I wonder if is there a better, smarter, cleaner or just more elegant way of doing that. The class I TDD out is this : module Elasticrepo class RepoSubset attr_reader :id, :owner, :name, :url, :description, :created_at, :pushed_at, :organization, :full_name, :language, :updated_at def initialize(attributes) #id = attributes["id"] #owner = attributes["owner"]["login"] #name = attributes["name"] #url = attributes["url"] #description = attributes["description"] #created_at = attributes["created_at"] #pushed_at = attributes["pushed_at"] #organization = attributes["owner"]["type"] #full_name = attributes["full_name"] #language = attributes["language"] #updated_at = attributes["updated_at"] end end end
I would remove the individual context blocks. They don't add any additional information.
I'd use a map of keys/values and iterate, or create an object with the correct values and compare the entire object.
How can I assert on initialize behaviour with RSpec?
I have a message class, which can be initialized by passing arguments into the constructor, or by passing no arguments and then setting the attributes later with accessors. There is some pre-processing going on in the setter methods of the attributes. I've got tests which ensure the setter methods do what they're supposed to, but I can't seem to figure out a good way of testing that the initialize method actually calls the setters. class Message attr_accessor :body attr_accessor :recipients attr_accessor :options def initialize(message=nil, recipients=nil, options=nil) self.body = message if message self.recipients = recipients if recipients self.options = options if options end def body=(body) #body = body.strip_html end def recipients=(recipients) #recipients = [] [*recipients].each do |recipient| self.add_recipient(recipient) end end end
I would tend to test the behaviour of the initializer, i.e. that its setup the variables how you would expect. Not getting caught up in the actuality of how you do it, assume that the underlying accessors work, or alternatively you could set the instance variables if you wanted. Its almost a good old fashioned unit test. e.g. describe "initialize" do let(:body) { "some text" } let(:people) { ["Mr Bob","Mr Man"] } let(:my_options) { { :opts => "are here" } } subject { Message.new body, people, my_options } its(:message) { should == body } its(:recipients) { should == people } its(:options) { should == my_options } end