MongoEngine not saving embedded doc second time around - mongodb

When I use MongoEngine to add an embedded doc to a doc, it works the first time when the list is empty but fails with subsequent tries saying: mongoengine.errors.OperationError: Could not save document (Cannot update 'sensorlist.1.alert_list.0._cls' and 'sensorlist.1.alert_list' at the same time)
The following test code demonstrates the issue: If you run it once you will see a new collection/document in foo that has an S2 embedded Sensor with qty 2 embedded Alerts. If you run it again it blows up - Any ideas?
Thx Bill
import mongoengine as ME
ME.connect('foo')
class Sensor(ME.EmbeddedDocument):
name = ME.StringField()
alert_list = ME.ListField()
class Alert(ME.EmbeddedDocument):
name = ME.StringField(default = 'new alert')
class SiteConfig(ME.Document):
siteid = ME.StringField()
sensorlist = ME.ListField(ME.EmbeddedDocumentField(Sensor))
if not SiteConfig.objects(siteid = '123456'):
newsite = SiteConfig(siteid = '123456')
newsite.save()
print("saved new site")
site = SiteConfig.objects(siteid = '123456').first()
newsensor = Sensor(name='S1')
site.sensorlist.append(newsensor)
site.save()
print("added sensor S1")
newsensor = Sensor(name='S2')
site.sensorlist.append(newsensor)
site.save()
print("added sensor S2")
for sensor in site.sensorlist:
if sensor.name =='S2':
alert = Alert()
sensor.alert_list.append(alert)
site.save()
print('added first alert to S2')
for sensor in site.sensorlist:
if sensor.name =='S2':
alert = Alert()
sensor.alert_list.append(alert)
site.save()
print('added second alert to S1')

I solved this by reproducing the code in MongoAlchemy which is very similar. That also failed but actually gave me useful exception info that pointed me to the problem which was that my Sensor class Alert_list definition needed to specify the class it contains.
So the fix is to define Sensor like this:
class Sensor(ME.DynamicEmbeddedDocument):
name = ME.StringField()
alert_list = ME.ListField(ME.EmbeddedDocumentField(Alert))
After all that pain over such a small issue I will probably stick with MongoAlchemy!

Related

Getting error 'Insight.Database.FastExpando' does not contain a definition for 'Set1'

The following code is giving the above error, and I cannot figure out why:
var x = _sqlConn.Connection().QueryResults<Results>("MyDb.dbo.get_records", new { id = theId });
int retVal = x.Outputs.Return_Value;
if (retVal == 0) // ...meaning result set was also returned...fine to this point.
{
var list = x.Outputs.Set1; // exception thrown here with above error
var temp = list.FirstOrDefault();
I have been using other features of Insight.Database for a number of years, but have not had to retrieve a SQL RETURN value at the same time as a recordset. The SQL itself works correctly in SSMS, returning a result set and the RETURN value of 0, as expected. This is happening in VS2019, .NET 4 and .NET 4.5.2; Insight.Database 5.2.7 and 5.2.8.
I got this code from the following page:
https://github.com/jonwagner/Insight.Database/wiki/Specifying-Result-Structures
where it shows this:
var results = connection.QueryResults<Beer, Glass>("GetAllBeersAndAllGlasses");
IList<Beer> beers = results.Set1;
which I combined with the following code from here:
https://github.com/jonwagner/Insight.Database/wiki/Output-Parameters
var results = connection.QueryResults<Results>("MyProc", inputParameters);
var p = results.Outputs.p;
That part works. It's accessing .Set1 that is failing, and I am not sure how to track down why.
I do not have experience with the FastExpando class, but Jon promised magic, and I want to believe. Thanks for any help.
I haven’t tried results+dynamic objects in a while…
I think it is because you are doing:
QueryResults<Results> and Results is an Insight type
You probably want:
QueryResults<MyType>
And then you get back a Results<MyType>
Which contains the return val and Set1
If not, post a ticket over on github and we will help you out.

Querying average with a function of column in Rails

I'm using Rails 4 in a web app, Postgresql database and squeel gem for queries.
I have this function in my model statistic.rb
def properties_mean_ppm(mode, rooms, type, output_currency_id)
sql_result = properties(mode, rooms, type).select{
avg(price_dolar / property_area).as(prom)
}
avg = sql_result[0].prom
final_avg = change_currency(avg, DOLAR_ID, output_currency_id)
return final_avg.to_f
end
price_dolar and property_area are columns in the properties table.
It works fine in Rails console and displays the result, but when I use it on the controller it gives an error:
ActiveModel::MissingAttributeError (missing attribute: id)
And indicates the line
avg = sql_result.to_a[0].prom
I also tried using sql_result[0].prom or sql_result.take or sql_result.first, they all have the same error.
The sql_result is this:
#<ActiveRecord::Relation [#<Property >]>
This is the action called in the controller
def properties_mean_ppm
#statistic = Statistic.find(params[:id])
mode = params[:mode] ? params[:mode] : ANY_MODE
type = params[:type] ? params[:type] : ANY_TYPE
one_room = #statistic.properties_mean_ppm(mode, 1, type, UF)
end
I know how to get the result using only SQL without activerecord but that would be very inefficient for me because I have lots of filters called before in the properties() function
Seems like calling that from the properties object made the controller to expect a Property with an id as a result. So I made it work without squeel.
sql_result = properties(mode, rooms, type).select(
"avg(precio_dolar / dimension_propiedad) as prom, 1 as id"
)
And giving a fixed id to the result

How to read UnitPrice from invoice line in QBO API v3 .NET

The bizarre properties in the .NET SDK continue to baffle me. How do I read the UnitPrice from an invoice line?
If I do this:
sild = (SalesItemLineDetail)line.AnyIntuitObject;
ln = new QBInvoiceLine(); // My internal line item class
ln.Description = line.Description;
ln.ItemRef = new QBRef() { Id = sild.ItemRef.Value, Name = sild.ItemRef.name };
if (sild.QtySpecified)
ln.Quantity = sild.Qty;
else
ln.Quantity = 0;
if (sild.ItemElementName == ItemChoiceType.UnitPrice)
ln.Rate = (decimal)sild.AnyIntuitObject; // Exception thrown here
The last line throws an invalid cast exception, even though the debugger shows that the value is 20. I've tried other types but get the same exception no matter what I do. So I finally punted and am calculating the rate like so:
ln.Rate = line.Amount / ln.Quantity;
(With proper rounding and checking for divide by zero, of course)
While we're on the subject... I noticed that in many cases ItemElementName == ItemChoiceType.PriceLevelRef. What's up with that? As far as I know, QBO doesn't support price levels, and I certainly wasn't using a price level with this invoice or customer. In this case I was also able to get what I needed from the Amount property.
Try this-
SalesItemLineDetail a1 = (SalesItemLineDetail)invoice11.Line[0].AnyIntuitObject;
object unitprice = a1.AnyIntuitObject;
decimal quantity = a1.Qty;
PriceLevelRef as an 'entity' is not supported. This means CRUD operations are not supported on this entity.
The service might however be returning readonly values in the transactions sometimes, but since this not mentioned in the docs, please consider it as unsupported.
Check that both request/response are in either json or xml format-
You can use the following code to set that-
ServiceContext context = new ServiceContext(appToken, realmId, intuitServiceType, reqvalidator);
context.IppConfiguration.Message.Request.SerializationFormat = Intuit.Ipp.Core.Configuration.SerializationFormat.Json;
context.IppConfiguration.Message.Response.SerializationFormat = Intuit.Ipp.Core.Configuration.SerializationFormat.Json;
Also, in QBO UI, check if Company->sales settings has Track Quantity and Price/rate turned on.

Trigger works but test doesn't cover 75% of the code

I have a trigger which works in the sandbox. The workflow checks the field in the campaign level and compares it with the custom setting. If it matches, then it returns the target to the DS Multiplier field. The trigger looks as follows
trigger PopulateTarget on Campaign (before insert, before update)
{
for(Campaign campaign : Trigger.new)
{
if (String.isNotBlank(campaign.Apex_Calculator__c) == true)
{
DSTargets__c targetInstance = DSTargets__c.getInstance(campaign.Apex_Calculator__c);
{
String target = targetInstance .Target__c;
campaign.DS_Target_Multiplier__c = Target;
}
}
}
}
However, I had problems to write a proper test to this and asked for the help on the internet. I received the test
#isTest
private class testPopulateTarget{
static testMethod void testMethod1(){
// Load the Custom Settings
DSTargets__c testSetting = new DSTargets__c(Name='Africa - 10 Weeks; CW 10',Target__c='0.1538', SetupOwnerId = apexCalculatorUserId);
insert testSetting;
// Create Campaign. Since it would execute trigger, put it in start and stoptests
Test.startTest();
Campaign testCamp = new Campaign();
// populate all reqd. fields.
testCamp.Name = 'test DS campaign';
testCamp.RecordTypeId = '012200000001b3v';
testCamp.Started_Campaign_weeks_before_Event__c = '12 Weeks';
testCamp.ParentId= '701g0000000EZRk';
insert testCamp;
Test.stopTest();
testCamp = [Select ID,Apex_Calculator__c,DS_Target_Multiplier__c from Campaign where Id = :testCamp.Id];
system.assertEquals(testCamp.DS_Target_Multiplier__c,testSetting.Target__c);// assert that target is populated right
}
}
Such test returns the error "Compile Error: Variable does not exist: apexCalculatorUserId at line 6 column 122". If I remove that ApexCalculator part System.assertEquals then the test passes. However it covers 4/6 part of the code (which is 66%)
Could anyone help me how should I amend the code to make the coverage of 75%?
Yes, apexCalculatorUserId has not been defined. The code you were given appears to be incomplete. You'll need to look at the constructor DSTargets__c and see what kind of ID it is expecting there.
At a guess, you could try UserInfo.getUserId() to get the ID of the current user, but that may not be the ID that's expected in the constructor. It would be worth trying it to see if the test coverage improves.
1) Replace apexCalculatorUserId with UserInfo.getUserId()
2) I'm not sure what kind of field is Apex_Calculator__c on campaign. If its not a formula you want to insert a new line before "insert testCamp". Something like:
testCamp.Apex_Calculator__c = UserInfo.getUserId();

How to get the underlying object from a SpyMessage in JBossMQ

I am trying to write a simple Java program that reads from JBossMQ's jms_messages table using JDBC. I am using JBoss 4.0.4.GA.
I can get the as far as getting a SpyMessage, but how can I get the actual message content (which is an Object in the particular case I'm looking at).
I have a result set "rs" from this statement:
SELECT messageid, messageblob FROM jms_messages WHERE DESTINATION LIKE 'TOPIC.MyTopic%' limit 3"
and then I do this (based on JBoss code):
long messageid = rs.getLong(1);
SpyMessage message = null;
byte[] st = rs.getBytes(2);
ByteArrayInputStream baip = new ByteArrayInputStream(st);
ObjectInputStream ois = new ObjectInputStream(baip);
message = SpyMessage.readMessage(ois);
message.header.messageId = messageid;
String jmstype = message.getJMSType();
String jms_message_id = message.getJMSMessageID();
System.out.println("jmstype=" +jmstype);
System.out.println("jms_message_id=" +jms_message_id);
String propertyName;
Enumeration e = message.getPropertyNames();
while (e.hasMoreElements())
{
propertyName = (String)e.nextElement();
System.out.println("property name = " +propertyName);
}
but I get no properties printed and I don't know how to get my actual object from the SpyMessage (actually a SpyObjectMessage). I'd be grateful for any pointers.
I've tried asking this question on the JBoss forum without reply, so I'm hoping for better luck here.
Thanks.
Sorry - the answer was so obvious I'm not really sure what I was thinking when I posted the question - simply:
Object objMessage = ((SpyObjectMessage)message).getObject();