Having both object.property and object.property.method() available in coffeescript - coffeescript

[update]
My question may not be clear enough...
Further clarification of what I would like to accomplish :
I retrieve objects like this one:
p =
name:
first: 'alan'
last: 'smith'
and want to create a structure (one class, multiple classes ?) to be able to write things like this ultimately:
person.name # alan smith
person.name.toCap() #Alan Smith
person.name.first # alan
person.name.first.toCap() # Alan
person.name.last # smith
person.name.last.toCap() # Smith
...
so :
Is there a way to have both person.name and person.name.first ?
Is there a better way to extend object properties with methods rather than extending native types like String ?
[original]
Looking for the right way to do this in coffee :
console.log person.name.last #smith
console.log person.name.last.capitalize() # SMITH
console.log person.name.last.initial() # S
I have come up with the following solution, but would like to make sure this is the way to go...
String::toCap = (remainingToLower=false) ->
#[0].toUpperCase() + if remainingToLower then #[1..-1].toLowerCase()
else #[1..-1]
Number::random = (percent) ->
offset = # * percent / 100
parseInt(Math.floor(Math.random() * 2 * offset) + # - offset)
class Name
constructor: (#first, #last) ->
class Person
constructor: (#name, #age) ->
toString: () => "#{#name.first.toCap(true)} #{#name.last.toCap(true)}
(#{#age.random(25)})"
# GO --------------------------->
p = new Person(new Name, 18)
p.name.first = 'alaN'
p.name.last = 'smith'
console.log "#{p.toString()}"
Thanks for your feedback.
Plunk Here

Context
I have this raw data:
data =
name:
first: 'alan'
last: 'smith'
age: 18
address: [
{
name: 'work'
street: '1600 amphitheatre parkway'
city: 'mountain view'
zip: 'CA 94043'
},{
name: 'home'
street: '1 infinite loop'
city: 'cupertino'
zip: 'CA 95014'
}]
And want to create a structure to manipulate my data like this :
p = New Person(data)
console.log """
#{p} # alan smith (18), 2 address lines
#{p.name}, # alan smith
#{p.name.first}, # alan
#{p.address} # 2 address lines
#{p.address.work} # 1600 amphitheatre parkway, mountain view, CA 94043
#{p.address.work.street} # 1600 amphitheatre parkway
"""
Additionally, I want to be able to apply custom methods to any member.
For instance, assuming toCap() is a method that capitalises each word of a String :
console.log """
#{p.name.toCap()}, # Alan Smith
#{p.name.first.toCap()} # Alan
#{p.address.work.toCap()} # 1600 Amphitheatre Parkway, Moutain View, CA 94043
#{p.address.work.street.toCap()} # 1600 Amphitheatre Parkway
"""
Solution (see this Plunk for the full code)
use nested classes
class Person
constructor: (data) ->
#name = new Name(data.name)
#address = new AddressList(data.address)
create members dynamically
class AddressList
constructor: (list) ->
#[addr.name] = new Address(addr) for addr in list
wrap your properties or use base classes rather than extending native objects
class StringProperty
constructor: (#_value) ->
toString: =>
#_value
toCap: (remainingToLower=false) =>
_words = #_value.split ' '
(#_toCap(w,remainingToLower) for w in _words).join ' '
_toCap : (s, r) ->
s[0].toUpperCase() + if r then s[1..-1].toLowerCase() else s[1..-1]
... and use them directly ...
class Name
constructor: (name) ->
#first = new StringProperty(name.first)
#last = new StringProperty(name.last)
toString: =>
"#{#first} #{#last}"
toCap: =>
"#{#first.toCap()} #{#last.toCap()}"
... or create members dynamically :
#[k] = new StringProperty(data[k]) for k of data when k in Address.fields
don't forget to override toString() as above

Related

object has no attribute 'dlg'

I'm trying to create a plugin for a Uni-subject which will receive a zipcode from a user and return the name of the corresponding location.
I have created the plugin layout, through the Plugin Builder and have designed the graphical interface with QtDesigner https://i.stack.imgur.com/h6k6Q.png . I have also added the .txt file that contains the zipcodes database to the plugin folder.
However, when I reload the plugin it gives me the error "object has no attribute 'dlg'" error message
Could you give me some guidance here and point me to where the problem could be? I am new to plugin development and python. Thanks
The code is this one:
import os
import sys
import qgis.core
from qgis.PyQt import uic
from qgis.PyQt import (
QtCore,
QtWidgets
)
import geocoder
# This loads your .ui file so that PyQt can populate your plugin with the elements from Qt Designer
FORM_CLASS, _ = uic.loadUiType(os.path.join(
os.path.dirname(__file__), 'example_dialog_base.ui'))
class ExampleDialog(QtWidgets.QDialog, FORM_CLASS):
POSTAL_CODES_PATH = ":/plugins/example/todos_cp.txt"
def __init__(self, parent=None):
"""Constructor."""
super(ExampleDialog, self).__init__(parent)
# Set up the user interface from Designer through FORM_CLASS.
# After self.setupUi() you can access any designer object by doing
# self.<objectname>, and you can use autoconnect slots - see
# http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html
# #widgets-and-dialogs-with-auto-connect
self.setupUi(self)
#self.QpushButton.clicked.connect(self.print_hello_world)
self.QlineEdit.textChanged.connect(self.toggle_find_button)
self.find_code_btn.clicked.connect(self.execute)
#def print_hello_world(self):
#print('Hello World!')
def toggle_find_button(self):
if self.QlineEdit.text() == "":
self.find_code_btn.setEnabled(False)
else:
self.find_code_btn.setEnabled(True)
def find_record(self, main_code, extension):
file_handler = QtCore.QFile(self.POSTAL_CODES_PATH)
file_handler.open(QtCore.QIODevice.ReadOnly)
stream = QtCore.QTextStream(file_handler)
while not stream.atEnd():
line = stream.readLine()
info = line.split(";")
code1 = info[-3]
code2 = info[-2]
if code1 == main_code and code2 == extension:
result = info
break
else:
raise RuntimeError("Sem resultados")
return result
def handle_layer_creation(self, record):
place_name = record[3]
point = geocode_place_name(place_name)
print("lon: {} - lat: {}".format(point.x(), point.y()))
layer = create_point_layer(
point,
f"found_location_for_{record[-3]}_{record[-2]}",
place_name
)
current_project = qgis.core.QgsProject.instance()
current_project.addMapLayer(layer)
def show_error(self, message):
message_bar = self.iface.messageBar()
message_bar.pushMessage("Error", message, level=message_bar.Critical)
def validate_postal_code(raw_postal_code):
code1, code2 = raw_postal_code.partition("-")[::2]
if code1 == "" or code2 == "":
raise ValueError(
"Incorrect postal code: {!r}".format(raw_postal_code))
return code1, code2
def geocode_place_name(place_name):
geocoder_object = geocoder.osm(place_name)
lon = geocoder_object.json.get("lng")
lat = geocoder_object.json.get("lat")
if lat is None or lon is None:
raise RuntimeError(
"Could not retrieve lon/lat for "
"place: {!r}".format(place_name)
)
point = qgis.core.QgsPointXY(lon, lat)
return point
def create_point_layer(point, layer_name, place_name):
layer = qgis.core.QgsVectorLayer(
"Point?crs=epsg:4326&field=address:string(100)",
layer_name,
"memory"
)
provider = layer.dataProvider()
geometry = qgis.core.QgsGeometry.fromPointXY(point)
feature = qgis.core.QgsFeature()
feature.setGeometry(geometry)
feature.setAttributes([place_name])
provider.addFeatures([feature])
layer.updateExtents()
return layer

Unable to parse module: unexpected = expecting indentation at column 1 or end of input

Wrote this code
module Main where
import Prelude
import Data.List (List)
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Console (CONSOLE, log)
type Entry = {
firstName :: String,
lastName :: String,
address :: Address
}
type Address = {
street :: String,
city :: String,
state :: String
}
type AddressBook = List Entry
showEntry :: Entry -> String
showEntry entry = entry.lastName <> ", " <>
entry.firstName <> ", " <>
showAddress entry.address
showAddress :: Address -> String
showAddress address = address.street <> ", " <>
address.city <> ", " <>
address.state
main :: forall e. Eff (console :: CONSOLE | e) Unit
main = do
log "Hello Sailor!"
address = {street: "123 Fake St.", city: "Faketown", state: "CA"}
showAddress address
everything is indented with two spaces
I get error
Error found:
at src/Main.purs line 34, column 11 - line 34, column 11
Unable to parse module:
unexpected =
expecting indentation at column 1 or end of input
See https://github.com/purescript/documentation/blob/master/errors/ErrorParsingModule.md for more information,
or to contribute content related to this error.
I also tried
main = do
log "Hello Sailor!"
address :: Address
address = {street: "123 Fake St.", city: "Faketown", state: "CA"}
showAddress address
but still get the same error.
You can't have out-of-the-blue bindings within a do notation, or indeed anywhere except top-level.
If you want to name an intermediate value, you have to use let:
main = do
log "Hello Sailor!"
let address = {street: "123 Fake St.", city: "Faketown", state: "CA"}
showAddress address
In your case, since address doesn't depend on the previous code, you can also bind it with where:
main = do
log "Hello Sailor!"
showAddress address
where
address = {street: "123 Fake St.", city: "Faketown", state: "CA"}
And even at top level, you can't have bindings that just stand on their own. See that where at the very top after module Main? That means everything inside this module is where-bound.
So the correct statement would be this: bindings can never stand on their own, they always have to be either let- or where-bound.
Also note: you can have multiple bindings inside a single let or a single where:
f x = do
let y = a + 42
z = y * b
pure $ z - 3
where
a = x + 1
b = a * 2

parameterize queries in OrientDB using placeholders

I am using pyorient and and want to parameterize queries -- I am assuming that command() allows placeholders, but am not able to find any documentation. IN particular I'd like to use dict() args as per postgres' %(name)s construct, but could make tuples/lists work as well.
I tried your case with my python_test database:
Dataset:
I used two parameters:
name ---> string;
surname ---> string;
and I passed them into the command() function.
PyOrient Code:
import pyorient
db_name = 'python_test'
user = 'root'
pwd = 'root'
print("Connecting...")
client = pyorient.OrientDB("localhost",2424)
session_id = client.connect(user, pwd)
print("OK - sessionID: ",session_id,"\n")
if client.db_exists( db_name, pyorient.STORAGE_TYPE_PLOCAL ):
print("DB "+db_name+" already exists\n")
client.db_open(db_name, user, pwd, pyorient.DB_TYPE_GRAPH, pyorient.STORAGE_TYPE_PLOCAL)
name = 'test name'
surname = 'test surname'
vertexes = client.command("SELECT FROM TestClass WHERE name = '" + name + "' AND surname = '" + surname + "'")
for vertex in vertexes:
print(vertex)
else:
print("Creating DB "+ db_name + "...")
client.db_create( db_name, pyorient.DB_TYPE_GRAPH, pyorient.STORAGE_TYPE_PLOCAL )
print("DB " + db_name + " created\n")
client.db_close()
Output:
Connecting...
OK - sessionID: 40
DB python_test already exists
{'#TestClass':{'surname': 'test surname', 'name': 'test name'},'version':1,'rid':'#12:0'}
Hope it helps

How can a document claim it's persisted, when a count on the class returns 0?

How can a document claim foo.persisted? == true, when foo.class.count == 0?
More importantly, how can I get the document to truly persist?
Update: calling Mongo::Foo.create() from the controller does increment the count. That is expected. Calling create, or new and save, from within a separate module/class does not increment the count.
Update: I have tried changing new/save calls to create
Update: I have also tried #foo_class.with(collection: "mongo_foos").create
[42] pry(#<FoosController>)> foo.class
=> Mongo::Foo
[43] pry(#<FoosController>)> foo.persisted?
=> true
[44] pry(#<FoosController>)> Mongo::Foo.count
=> 0
[47] pry(#<FoosController>)> foo.id
=> "5081a1a786ddc8e035000021"
[48] pry(#<FoosController>)> foo
=> #<Mongo::Foo _id: 5081a1a786ddc8e035000021, _type: nil, foo_daddy_id: nil, old_foo_daddy_id: 219, member_id: "F008AR", unix_time: nil, date_time: 2012-10-19 13:50:54 UTC, submitted: nil, json: nil>
Here's how the document class is defined:
module Mongo
class Foo
include Mongoid::Document
field :foo_daddy_id
field :old_foo_daddy_id, type: Integer
field :member_id, type: String
field :unix_time, type: Integer
field :date_time, type: DateTime
field :submitted, type: Integer
field :json, type: Hash
belongs_to :foo_daddy, class_name: "Mongo::FooDaddy"
embeds_many :foo_dumplings, class_name: "Mongo::FooDumpling"
end
end
The doc is being created with foo.new(params); foo.save:
module FooThingy
module Foo
class Create < ::FooThingy::Base
def initialize(options)
# Sets instance variables used below
end
def execute!
#foo = #foo_class.new({
date_time: DateTime.strptime(#params["submitted_timestamp"], "%m-%d-%Y %H:%M:%S"),
member_id: (#params[:member_id].present? ? #params[:member_id] : nil),
old_foo_daddy_id: #params[:old_foo_daddy_id]
})
embed_foo_dumplings
if #foo.save
return FooThingy::Result.new(success: true, data: { foo: #foo })
else
return FooThingy::Result.new(success: false, data: { foo: #foo })
end
end
private
def embed_foo_dumplings
# Embeds foo_dumplings
end
end
end
end
Here's where I call that module to create the document:
class FoosController < ApplicationController
def create
foo_creator = FooThingy::Foo::Create.new(params: params, foo_class: Mongo::Foo)
foo = foo_creator.execute!
foo = foo.data[:foo]
binding.pry
end
end
This problem, I think, is less interesting than it appears. I've modified my config/mongoid.yml to specify a new database, and everything behaves as expected. Problem was likely due to limitations on 32-bit MongoDB installations.

Mail functionality using OPA

import stdlib.web.mail
from = {name="name" address={local="username" domain="gmail.com"}}
to = {name="name" address={local="username" domain="gmail.com"}}
r = Email.try_send(from, to, "Subject", {text = "This is Great!"})
server = Server.one_page_server("Mail", [], [], r)
the following error I'm getting
Error
File "mail.opa", line 6, characters 4-66, (6:4-6:66 | 166-228)
Function was found of type
Email.email, Email.email, string, Email.content -> Email.send_status but
application expects it to be of type
{ address: { domain: string; local: string } / 'c.b; name: string } / 'c.a,
{ address: { domain: string; local: string } / 'c.d; name: string } / 'c.c,
string, { text: string } / 'c.e -> 'a.
Types string and { none } / { some: string } are not compatible
Hint:
Error occurred through field name.
Can anyone help me with Mail functionality in Opa?
There is a number of problems with this code:
Notice that in Email.email type the name field is optional; so if you want to include it you should provide some("name"), not just "name"
Server.one_page_server contains 2 arguments not 4.
The last argument to one_page_server should be the xhtml of the page, whereas your r is the result of sending an email.
After those fixes your code could look something like this:
import stdlib.web.mail
from = {name=some("name") address={local="username" domain="gmail.com"}} : Email.email
to = {name=some("name") address={local="username" domain="gmail.com"}} : Email.email
page() =
status = Email.try_send(from, to, "Subject", {text = "This is Great!"})
<>Email sent</>
server = Server.one_page_server("Mail", page)