Uploading multiple attachments with rails, paperclip, and angularjs - ruby-on-rails

I've been stuck on this issue for a couple of days and seem to have run into a wall. I am using rails 4.1, angular 1.2.23, and paperclip 4.1. I sampled from many of the solution for similar problems but none seem to have resolved the issue.
When I set up the paperclip attachments inside of the doc model, I was able to upload a single attachment. However, when I separated the attachments from the doc model and added the images model for multiple attachments, I couldn't get it to work.
Here is the code I am using:
doc.rb
class Doc < ActiveRecord::Base
has_many :image, :dependent => :destroy
accepts_nested_attributes_for :image, :reject_if => lambda { |a| a[:content].blank? }, :allow_destroy => true
end
image.rb
class Image < ActiveRecord::Base
belongs_to :doc
has_attached_file :image, :styles => { :lrg => "700x700>", :med => "350x350>", :sml => "100x100>" }, :whiny => false,
:path => ":rails_root/public/system/:attachment/:id/:style/:filename",
:url => "/system/:attachment/:id/:style/:filename"
validates_attachment_content_type :image, :content_type => /\Aimage\/.*\Z/
def image=(files = [])
files.each{|f| (#image ||= []) << image.create(image: f) }
end
end
Here is my controller:
class DocsController < ApplicationController
skip_before_filter :verify_authenticity_token
def index
#docs = if params[:keywords]
Doc.where("title ilike ?", "%#{params[:keywords]}%")
else
[]
end
#items = Doc.all
end
def show
#doc = Doc.find(params[:id])
end
def create
if params[:imageData]
decode_image
#doc = Doc.new(#up)
else
#doc = Doc.new(params.require(:doc).permit(:id, :title, :parent, :info))
end
if #doc.save
render 'show', status: 201
else
render json: #doc.errors, status: :unprocessable_entity
Rails.logger.info #doc.errors
end
end
def update
doc = Doc.find(params[:id])
if params[:imageData]
decode_image
doc.update_attributes(#up)
else
doc.update_attributes(params.require(:doc).permit(:id, :title, :parent, :info))
end
head :no_content
end
def destroy
doc = Doc.find(params[:id])
doc.destroy
head :no_content
end
private
def doc_params
#up = params.require(:doc).permit(:id, :title, :parent, :info, image_attributes: [:_destroy, :id, :image])
end
def decode_image
#up = params.require(:doc).permit(:id, :title, :parent, :info, image_attributes: [:_destroy, :id, :image])
# decode base64 string
Rails.logger.info 'decoding now'
decoded_data = Base64.decode64(params[:imageData]) # json parameter set in directive scope
# create 'file' understandable by Paperclip
#data = StringIO.new(decoded_data)
#data.class_eval do
attr_accessor :content_type, :original_filename
end
# set file properties
#data.content_type = params[:imageContent] # json parameter set in directive scope
#data.original_filename = params[:imagePath] # json parameter set in directive scope
# update hash, I had to set #up to persist the hash so I can pass it for saving
# since set_params returns a new hash everytime it is called (and must be used to explicitly list which params are allowed otherwise it throws an exception)
#up[image_attributes: [:image]] = #data # image is the model attribute that is defined as an attachment using paperclip generator
end
end
Here is my upload directive using angular:
angular.module('fileUpload', []) // using restangular is optional
.directive('uploadImage', function () {
return {
restrict: 'A',
link: function (scope, elem, attrs) {
// listens on change event
elem.on('change', function() {
console.log('entered change function');
for (var i = 0; i < elem.length; i++) {
for (var x = 0; x < elem[i].files.length; x++) {
var file = elem[i].files[x];
// gathers file data (filename and type) to send in json
scope.doc.imageContent = file.type;
scope.doc.imagePath = file.name;
console.log(scope.doc.imagePath);
// converts file to binary string
var reader = new FileReader();
reader.readAsBinaryString(file);
reader.onload = function (e) {
// retrieves the image data from the reader.readAsBinaryString method and stores as data
// calls the uploadImage method, which does a post or put request to server
scope.doc.imageData = btoa(e.target.result);
// updates scope
}
scope.uploadImage(scope.doc.imagePath);
scope.$apply();
}
};
});
},
controller: ['$scope', '$location', '$resource', function($scope, $location, $resource){
$scope.uploadImage = function (path) {
var Doc;
Doc = $resource('/docs/:docId', {
docId: "#id",
format: 'json'
}, {
'save': {
method: 'PUT'
},
'create': {
method: 'POST'
}
});
// if updating doc
console.log($scope.doc);
var onError;
onError = function(_httpResponse) {
return flash.error = "Something went wrong";
};
if ($scope.doc.id) {
$scope.doc.$save((function() {
$scope.docImageLink = baseUrl + $scope.doc.image_url;
}), onError);
} else {
console.log("create");
}
};
}]
};
});
And finally, here is my form field:
<input type="file" id="doc.image" name="doc.image" ng-model='doc.image' upload-image multiple/>
<img ng-src="{{userImageLink}}" ng-click="openFileWindow()" ng-class="{ hidden: !userImageLink}" >
<div class="drop-box" ng-click="openFileWindow()" ng-class=" {hidden: userImageLink}">
Add Image
</div>
When I submit the form with multiple attachments, I receive this error in the rails log:
ActiveRecord::UnknownAttributeError (unknown attribute: {:image_attributes=>[:image]}):
app/controllers/docs_controller.rb:21:in `create'
This is my first major rails app so any help would be significantly appreciated. I can also provide any follow up information that is required.
Thanks!

Related

Uploading files by ng-file-upload and paperclip

I spent a lot of times with ng-file-upload and rails paperclip and stuck((. In standard view with new.html.erb paperclip works perfect. But with ng-file-upload browser returns an error.
Internal Server Error
bad content body
Or if I change upload in my controller:
afisha: {file: file} => to file: {file: file}
Routing Error:
Routing Error
No route matches [POST] "/public"
Here is my controller:
$scope.upload = function (file) {
console.log(file);
Upload.upload({
url: 'http://localhost:3000/public',
method: 'POST',
afisha: {file: file}
}).then(function (resp) {
console.log('Success ' + resp.config.data.file.name + 'uploaded. Response: ' + resp.data);
}, function (resp) {
console.log('Error status: ' + resp.status);
}, function (evt) {
var progressPercentage = parseInt(100.0 * evt.loaded / evt.total);
console.log('progress: ' + progressPercentage + '% ' + evt.config.data.file.name);
});
};
View:
<button class="btn" ngf-select="upload($file)">Upload on file select</button>
Rails controller:
class EventsController < ApplicationController
respond_to :json
before_filter :authenticate_user!
def index
respond_with Event.all
end
def show
respond_with Event.find(params[:id])
end
def create
#event = Event.create(event_params)
#guests = guests_params[:guests].map { |guest|
Guest.create(name: guest[:name], surname: guest[:surname], event: #event)
}
respond_with #event
end
def destroy
#event = Event.find(params[:id])
#event.destroy
end
def authenticate_user!
if user_signed_in?
super
else
redirect_to login_path
end
end
private
def event_params
params.require(:event).permit(:name, :description, :date, :afisha)
end
def guests_params
params.permit(guests: [:name, :surname])
end
end
model:
class Event < ActiveRecord::Base
has_attached_file :afisha, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :afisha, content_type: /\Aimage\/.*\z/
has_many :guests
def as_json(options={})
super(options.merge(include: :guests))
.merge(:afisha => afisha.url)
end
end

How can i attach more than one file with Carrierwave / AngularJs+RoR via Json?

sorry for my english.
For now i can create Task with one picture attached to it, i want more...
I have Rails on back-end and AngularJS on front-end. I create a directive which helps me send image to server via json.
app.directive 'uploadImage', ->
return{
restrict: 'A'
link:(scope,elem)->
reader = new FileReader()
reader.onload =(e)->
scope.iFile = btoa(e.target.result)
scope.$apply()
elem.on 'change', ->
scope.iFile=''
file = elem[0].files[0]
scope.iFilesize = file.size
scope.iFiletype = file.type
scope.iFilename = file.name
scope.$apply()
reader.readAsBinaryString(file)
}
Create task in AngularJS:
$scope.createTask =->
$scope.task.iFile = $scope.iFile
$scope.task.iname = $scope.iFilename
$scope.task.itype = $scope.iFiletype
baseTasks.post($scope.task).then (data)->
$scope.tasks.unshift($scope.task)
$scope.go('/tasks')
,(error)->
# some code
On the server-side i have a model Task.rb with this settings :
require 'file_size_validator'
class Task < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_many :comments, as: :commentable, dependent: :destroy
validates_presence_of :title
validates_presence_of :text
validates_presence_of :price
mount_uploader :pict, ImageUploader
validates :pict,
:file_size => {
:maximum => 0.5.megabytes.to_i
}
end
and TasksController, action Create :
def create
params[:task][:pict] = parse_image_data(params[:iFile]) if params[:iFile]
#task = Task.new(task_params)
if #task.save
clean_tempfile
render_with_protection #task.to_json, {status: :created, location: #task }
else
render_with_protection #task.errors.to_json, {status: :unprocessable_entity }
end
end
private
def task_params
params.require(:task).permit(:desc, :text, :price, :title, :ed, :category_id, :pict, :user_id)
end
def parse_image_data(image_data)
Rails.logger.info 'decoding now'
decoded_data = Base64.decode64(image_data)
# create 'file' understandable by Carrierwave
#data = StringIO.new(decoded_data)
#tempfile = Tempfile.new('task-image')
#tempfile.binmode
#tempfile.write decoded_data
#tempfile.rewind
ActionDispatch::Http::UploadedFile.new(
:tempfile => #tempfile,
:content_type => params[:itype],
:filename => params[:iname]
)
end
def clean_tempfile
if #tempfile
#tempfile.close
#tempfile.unlink
end
end
Where i decoded image and attach it to model as Carrierwave need.
So please help me with attaching more than one image to my model.
Thanks in advance.
You have to loop through each image in your uploadImage directive like this :
reader = new FileReader()
reader.onload = (e) ->
scope.iFile = btoa(e.target.result)
scope.$apply()
elem.on "change", ->
i = 0
while i < elem.length
x = 0
while x < elem[i].files.length
file = elem[i].files[x]
scope.iFile = ""
scope.iFilesize = file.size
scope.iFiletype = file.type
scope.iFilename = file.name
scope.$apply()
reader.readAsBinaryString file
x++
i++
return
And in your html you should have multiple true in your file input.
<input type='file' ng-mpdel='abc' multiple>
Solved. I had to create model Image with polymorphic association.So my models are :
require 'file_size_validator'
class Image < ActiveRecord::Base
belongs_to :imageable, polymorphic: true
mount_uploader :picture, PictureUploader
validates :picture,
:file_size => {
:maximum => 0.5.megabytes.to_i
}
end
class Task < ActiveRecord::Base
belongs_to :user
belongs_to :category
has_many :comments, as: :commentable, dependent: :destroy
has_many :images, as: :imageable, dependent: :destroy
end
Code for upload images in a view:
<input type="file" multiple accept="image/png, image/gif, image/jpeg" upload-image/>
Create directive in angularJS with help #Nitin Verma (thank you!)
app.directive 'uploadImage', ['Restangular',(Restangular)->
baseImages = Restangular.all('images')
return{
restrict: 'A'
link: (scope, elem)->
elem.on 'change', ->
i = 0
im =[]
filD =[]
while i < elem.length
x = 0
while x < elem[i].files.length
reader = new FileReader()
reader.onload = (e)->
im.push(btoa(e.target.result))
scope.$apply()
file = elem[i].files[x]
scope.files = elem[0].files
scope.iFile = ""
filD[x]=[]
filD[x].push(file.type)
filD[x].push(file.name)
scope.$apply()
reader.readAsBinaryString file
x++
i++
scope.arImages = im
scope.fileInf = filD
return
}
]
And my $scope.createTask :
$scope.createTask =->
$scope.task.ed = $scope.edIz.name
$scope.task.category_id = $scope.category_id.id
$scope.task.user_id = $scope.curr.id
baseTasks.post($scope.task).then (data)->
$scope.taskId =data.id
i = 0
while i < $scope.arImages.length
$scope.image ={}
$scope.image.pict = $scope.arImages[i]
$scope.image.iname = $scope.fileInf[i][1]
$scope.image.itype = $scope.fileInf[i][0]
$scope.image.task_id =$scope.taskId
console.log($scope.image.task_id)
imageRes.save( $scope.image )
i++
$scope.tasks.unshift($scope.task)
$scope.go('/tasks')
,(error)->
flash.error = error
I had to use $resource, because double save with Restangular is hangs the app without errors. so :
app.factory('imageRes', ['$resource', ($resource)->
return $resource('/images/:id.json', {id: '#id'}, {
update: {method:'PUT'},
show: {method:'GET'},
delete: {method:'DELETE'}
})])
On the server side in ImagesController, action create:
def create
params[:image][:picture] = parse_image_data(params[:pict]) if params[:pict]
#image = Image.new(image_params)
clean_tempfile
if #image.save
# render_with_protection #task.to_json, {status: :created, location: #task }
render json: #image
else
render_with_protection #image.errors.to_json, {status: :unprocessable_entity }
end
end
Method parse_image_data is the same as in question description.
If anybody knows better way to solve this, please write it !

How to use filters in Magento SOAP API v1 with Rails 4 and Savon?

I'm building an app in Rails 4 using the Magento SOAP API v1 and Savon gem. Right now I am trying to get all orders with a status of pending. To hook into the API I am using this code:
class MagentoAPI
def self.call method, options={}
response = ##soap_client.request :call do
if options.empty?
soap.body = { :session => ##soap_session, :method => method }
elsif options[:string]
soap.body = { :session => ##soap_session, :method => method, :arguments => [options[:string]] }
else
puts options
soap.body = { :session => ##soap_session, :method => method, :arguments => options }
end
end
if response.success?
# listing found products
final = []
call_return = response[:call_response][:call_return]
return [] if call_return[:item].nil?
raw = call_return[:item]
if raw.is_a? Hash # this is a list of one item
final << raw[:item].inject({}){|x,y| x.merge(y[:key]=>y[:value])}
else
if raw[0][:item].nil? # this is a product info
return raw.inject({}){|x,y| x.merge(y[:key]=>y[:value])}
else # this is a list of many items
raw.each{|result| final << result[:item].inject({}){|x,y| x.merge(y[:key]=>y[:value])}}
end
end
final
end
end
end
And then this:
class Order
def self.get_all_active
activeOrders = MagentoAPI.call 'order.list', :filter => {:status => 'pending'}
end
end
This just returns Savon::HTTP::Error so I'm thinking I'm not formatting the request properly. Does anybody have any experience or insight on this?
Hope this isn't too late (assume it might be), but I created a gem for this with some rudimentary documentation. I'm hoping to finish it up this weekend or next week, but you can take a look at the code and see how I'm creating the filters for Magento. To install, just run:
gem install magento_api_wrapper
To summarize, if you want to use one of the Magento SOAP API simple filters, you can pass a hash with a key and value:
api = MagentoApiWrapper::Sales.new(magento_url: "yourmagentostore.com/index.php", magento_username: "soap_api_username", magento_api_key: "userkey123")
api.order_list(simple_filters: [{key: "status", value: "processing"}, {key: created_at, value: "12/10/2013 12:00" }])
And to use a complex filter, pass a hash with key, operator, and value:
api.order_list(complex_filters: [{key: "status", operator: "eq", value: ["processing", "completed"]}, {key: created_at, operator: "from", value: "12/10/2013" }])
This returns an array of hashes with all your Magento orders.
Specifically, check out the request code: https://github.com/harrisjb/magento_api_wrapper/blob/master/lib/magento_api_wrapper/requests/sales_order_list.rb
While it will be easier to just use the gem, here's how I'm formatting the request prior to passing it to the SavonClient, which finishes the formatting for Magento's SOAP API:
def body
merge_filters!(sales_order_list_hash)
end
def attributes
{ session_id: { "xsi:type" => "xsd:string" },
filters: { "xsi:type" => "ns1:filters" },
}
end
def sales_order_list_hash
{
session_id: self.session_id
}
end
def merge_filters!(sales_order_list_hash)
if !filters_array.empty?
sales_order_list_filters = {
filters: filters_array,
}
sales_order_list_hash.merge!(sales_order_list_filters)
else
sales_order_list_hash
end
end
def filters_array
custom_filters = {}
custom_filters.compare_by_identity
if !simple_filters.nil?
add_simple_filters(custom_filters)
end
if !complex_filters.nil?
add_complex_filters(custom_filters)
end
custom_filters
end
def add_simple_filters(custom_filters)
simple_filters.each do |sfilter|
custom_filters[:attributes!] = {
"filter" => {
"SOAP-ENC:arrayType" => "ns1:associativeEntity[2]",
"xsi:type" => "ns1:associativeArray"
}
}
custom_filters["filter"] = {
item: {
key: sfilter[:key],
value: sfilter[:value], #formatted_timestamp(created_at)
:attributes! => {
key: { "xsi:type" => "xsd:string" },
value: { "xsi:type" => "xsd:string" }
},
},
:attributes! => {
item: { "xsi:type" => "ns1:associativeEntity" },
},
}
end
custom_filters
end
def add_complex_filters(custom_filters)
complex_filters.each do |cfilter|
custom_filters[:attributes!] = {
"complex_filter" => {
"SOAP-ENC:arrayType" => "ns1:complexFilter[2]",
"xsi:type" => "ns1:complexFilterArray"
}
}
custom_filters["complex_filter"] = {
item: {
key: cfilter[:key],
value: {
key: cfilter[:operator],
value: cfilter[:value]
},
:attributes! => {
key: { "xsi:type" => "xsd:string" },
value: { "xsi:type" => "xsd:associativeEntity" }
},
},
:attributes! => {
item: { "xsi:type" => "ns1:complexFilter" },
},
}
end
custom_filters
end
def formatted_timestamp(timestamp)
begin
Time.parse(timestamp).strftime("%Y-%m-%d %H:%M:%S")
rescue MagentoApiWrapper::BadRequest => e
raise "Did you pass date in format YYYY-MM-DD? Error: #{e}"
end
end
def status_array
data[:status_array]
end
def created_at_from
data[:created_at_from]
end
def created_at_to
data[:created_at_to]
end
def last_modified
data[:last_modified]
end
def session_id
data[:session_id]
end
def simple_filters
data[:simple_filters]
end
def complex_filters
data[:complex_filters]
end
I've also got a SavonClient that does some of the configuration for the specific API, here's most of that:
def call
client.call(#request.call_name, message: message_with_attributes, response_parser: :nokogiri)
end
#message_with_attributes are required for some specific formatting when updating Magento via the SOAP API
def message_with_attributes
#request.body.merge!(:attributes! => #request.attributes) unless #request.attributes.empty?
puts "REQUEST: #{#request.inspect}"
return #request.body
end
#configuration of the client is mostly mandatory, however some of these options (like timeout) will be made configurable in the future
#TODO: make timeout configurable
def client
Savon::Client.new do |savon|
savon.ssl_verify_mode :none
savon.wsdl base_url
savon.namespaces namespaces
savon.env_namespace 'SOAP-ENV'
savon.raise_errors false
#savon.namespace_identifier #none
savon.convert_request_keys_to :lower_camelcase
savon.strip_namespaces true
savon.pretty_print_xml true
savon.log log_env
savon.open_timeout 10 #seconds
savon.read_timeout 45 #seconds
end
end
#TODO: make configurable
def log_env
true
end
#correctly format MagentoApiWrapper::Request call_names for SOAP v2
def response_tag_format_lambda
lambda { |key| key.snakecase.downcase }
end
def namespaces
{
'xmlns:SOAP-ENV' => 'http://schemas.xmlsoap.org/soap/envelope/',
'xmlns:ns1' => 'urn:Magento',
'xmlns:xsd' => 'http://www.w3.org/2001/XMLSchema',
'xmlns:xsi' => 'http://www.w3.org/2001/XMLSchema-instance',
'xmlns:SOAP-ENC' => 'http://schemas.xmlsoap.org/soap/encoding/',
'SOAP-ENV:encodingStyle' => 'http://schemas.xmlsoap.org/soap/encoding/'
}
end
#Use MagentoApiWrapper::Api magento_url as endpoint
def base_url
"#{#magento_url}/api/v2_soap?wsdl=1"
end
end
Like I said, it's a work in progress, but I should have pretty good coverage of the Magento API complete in the next couple of weeks. Hope this helps you out! Good luck!

Rails ActiveRecord relation to JSON

I'm using Rails to query data and put it into a hash like so...
class AssignmentsController < ApplicationController
respond_to :json
def index
student = Student.find(current_user.student_id)
#assignments = Hash.new
#assignments["individual"] = Assignment.where(:student_id => student.id)
unless student.group_lesson_ids.nil?
student.group_lesson_ids.each do |g|
group_lesson = GroupLesson.find(g)
#assignments[group_lesson.name] = Assignment.where(:group_lesson_id => g)
end
end
end
end
Then I want Rabl to turn this into JSON to be used by a Marionette app.
Here's the Rabl file
object #assignments
attributes :id, :title, :student_id, :assigned
But when I inspect the JSON in the browser, it just shows me the ActiveRecord relation.
{
"#<ActiveRecord::Relation::ActiveRecord_Relation_Assignment:0x007fa2956b43a8>": [
{ },
{ },
{ }
]
}
I understand this is because of the concept of lazy loading, but what should I do in this situation to make the JSON available to Marionette?
How about this, provided you have relationships between models specified (not tested since I'm not currently using RABL):
class AssignmentsController < ApplicationController
respond_to :json
def index
#student = current_user.student
end
end
RABL template:
object false
node :assignments do
child #student.assignments => :individual
#student.group_lessons.each do |gl|
node(gl.name) { gl.assignments }
end
end

Displaying a polygon with gmaps4rails

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.

Resources