Updating firebase path if it exists - ios

My app has bits of information that exist for 24 hrs. This information has the potential to be voted on by other users. The number of votes is recorded in the database. If someone votes on a piece of information, I want it to be updated only if the path currently exists, as the data may have reached the 24 hour limit and been deleted since the display time and the vote time.
The problem with using something like Datasnapshot.hasChild is that I will need to write 2 separate read and write instructions. The data may exist for the read instruction but then may reach the 24 hour mark and be deleted before the write instruction.
This is the structure of my database, the node status is duplicated in another part of the database in order to reduce the amount of reads. If this node becomes nil, the other one still exists, but this node is here so that I can do one write to obtain all the newest statuses that are less than 24 hours old.
I would like a rule that does not allow the value of votes to change if the key of status has changed, or if status is no longer a node.

There are a couple of ways to approach this.
One way is to leverage Firebase Rules. Before doing that, let me first say this to keep the Firebasers happy:
Rules are not filters
However, you can craft a rule that will prevent a write if a certain node does not exist. I would need to know your specific structure and use case to suggest a solution but Rules are pretty well covered in the Firebase Rules Docs andReferencing Data In Other Paths is a place to start.
But, a super clean an easy option is the following code that will only write to a node if it exists. One read and write.
func onlyWriteIfNodeExists() {
let ref = your_firebase.ref.child("may_not_exist")
ref.observeSingleEvent(of: .value, with: { snapshot in
if snapshot.exists() {
snapshot.ref.setValue("updated value")
} else {
print("node didn't exist")
}
})
}
and the structure would be
firebase_root
may_not_exist: "some value"
so if the node may_not_exist exists, "some value" will be replaced with "updated value" otherwise will will print "node didn't exist" to console.
That being said, if the intention is to not allow users to vote on items that don't exist, the UI should reflect that. In other words, if the app presents topics to vote on and a topic goes out of scope, the app should receive an event of that and perhaps remove it from the UI or draw a line through the topic heading to indicate it's no longer available.

Related

How to get count of each unique firebase child so only the developer can see (not the user)

I am trying to figure out a way to get a list of each unique child in my Firebase Database & get a count of each unique child.
So for example if somebody entered Amazon 5 times an Hulu 2 times. I want to be able to know that. However, I don't want the user to know this.
I had a few ideas on how to do this.
Idea 1
Use Firebase's:
Answers.logCustomEvent...
However, I see two flaws with this idea.
Flaw 1: This wouldn't be useful for data that has already been entered.
Flaw 2: A user could enter Amason on accident and then changes it later to be the correct Amazon. I would get the incorrect entry..I could log changes but then I'd get bad data...or at least confusing data.
Idea 2
I could write a function inside of the app that could do this, but like I said. I don't need this functionality in the app for the user. I want it so I can know which sites I need to add functionality for first over ones that are seldom entered.
However, is it possible to have 2 apps that use the same database? So the main app is able to read and write data. While I could create a simple app that I wouldn't publish, only really use for myself that could Read the data but not write to it...
I tried to make my Database flat as I knew how..
When a user adds a service it doesn't go under the user node, I have a child called "services" and I just reference that service child in the "user" child.
So my database looks like this
cards
card uid 1
cardname: ""
services
service uid 1: true
services
service uid 1
serviceName: Amazon
serviceUrl: ""
service uid 2
serviceName: Amazon
users
... reference the card this user has access to
So to repeat the question.
I want to be able to know each unique serviceName and if there are duplicates of the same one..how many there are..
I don't need to know who created it or when..
you may have another table where you have objects with only 2 fields: serviceName and count.
So, everytime you have a new instance, you check if it already persists in your table and increment the count value, otherwise create a new row.
Users will not see that info.
And, yes, you can access one database from several apps. Just get clientID, trackingID, etc...

Same step using different step definitions Serenity Cucumber

I am automating a system using BDD with Serenity + Cucumber-jvm, and I have some cases, that the same step can be used as any keyword step definition.
Example:
Given something
When do something
Then other thing
And do something
As you can see, do something is used with both when and then, but If I define the same method with these 2 annotations:
#When("do something")
#Then("do something")
public void doSomething() {
}
I get the following error:
cucumber.runtime.DuplicateStepDefinitionException: Duplicate step definitions in ...
How do I resolve this issue
"Given" describes the context in which the scenario takes place. It either describes a state, or it describes something that has happened. So phrase it in either the continuous present, or the past tense.
Given the invoice is two weeks late <-- continuous present
Given the invoice was submitted <-- past
You'll also notice that it doesn't say anything about who submitted the invoice. That's fine for the context, because it doesn't matter how it got there. We call this the "passive" as opposed to the "active" voice.
"When" describes an event that happens. I like to put this in the present tense, active voice. "The dog bit the boy" is active voice. "The boy was bitten" is passive since it doesn't mention who did it. By mentioning who does it, we remind people that there's a user involved, even if that user is another system.
When I check my accounts
When the admin creates a new record
When the ETL begins
"Then" describes what ought to happen, in that context, for that event. I like to use the word "should", which is a conditional tense. It's also in the passive voice because the "when" should cover how it happened.
Then the invoice should be marked as paid
Then I should receive an email <-- "I" am not the doer so this is still passive voice
The word "should" has an additional benefit. Back in the days of Waterfall development, we used to try to get all the requirements right, but we never quite managed it.
By using the word "should", we encapsulate the idea that uncertainty still exists. It encourages people to question whether the requirements are accurate, and in the face of changing technology and innovation, whether they're still accurate. It's easier to change an idea when it isn't using "must" or "will", as those are words which express certainty, and if you're convinced that someone else is certain about something, you're less likely to push back.
By pushing back and making other suggestions we get "exploration by example", and it's the precursor to specification or test by example, which are nice by-products. Ideally you'll be talking through more scenarios than you actually keep, and deciding which ones are in and out of scope. The word "should" really helps with that, and keeping it when you capture those scenarios and write them down helps too.
And, of course, it helps to differentiate "Given" and "Then" (but hopefully not "When" since that will be phrased in the active voice anyway).
So, if I were to use your "do something" example, I might say:
Given something was done
When someone does something
Then something else should have happened.
Now none of your scenario steps are similar, and you've clarified what you really mean by them, too.
I wrote a blog post on this a while back if it helps as a reference.
For Cucumber The keyword in front a step definition (Given,When,Then,And..) does not make any difference it is for lexical clarity and beauty. That said when you do
#When("do something")
#Then("do something")
is equivalent to:
#When("do something")
#When("do something")
or
#Then("do something")
#Then("do something")
So not to get duplicate step definitions you need just to look at the text not the keyword :)

Updating core data performance

I'm creating an app that uses core data to store information from a web server. When there's an internet connection, the app will check if there are any changes in the entries and update them. Now, I'm wondering which is the best way to go about it. Each entry in my database has a last updated timestamp. Which of these 2 will be more efficient:
Go through all entries and check the timestamp to see which entry needs to be updated.
Delete the whole entity and re-download everything again.
Sorry if this seems like an obvious question and thanks!
I'd say option 1 would be most efficient, as there is rarely a case where downloading everything (especially in a large database with large amounts of data) is more efficient than only downloading the parts that you need.
I recently did something similiar.
I solve the problem, by assigning an unique ID and a global 'updated timestamp' and thinking about 'delta' change.
I explain better, I have a global 'latest update' variable stored in user preferences, with a default value of 01/01/2010.
This is roughly my JSON service:
response: {
metadata: {latestUpdate: 2013...ecc}
entities: {....}
}
Then, this is what's going on:
pass the 'latest update' to the web service and retrieve a list of entities
update the core data store
if everything went fine with core data, the 'latestUpdate' from the service metadata became my new 'latest update variable' stored in user preferences
That's it. I am only retrieving the needed change, and of course the web service is structured to deliver a proper list. Which is: a web service backed by a database, can deal with this matter quite well, and leave the iphone to be a 'simple client' only.
But I have to say that for small amount of data, it is still quite performant (and more bug free) to download the whole list at each request.
As per our discussion in the comments above, you can model your core data object entries with version control like this
CoreDataEntityPerson:
name : String
name_version : int
image : BinaryData
image_version : int
You can now model the server xml in the following way:
<person>
<name>michael</name>
<name_version>1</name_version>
<image>string_converted_imageData</image>
<image_version>1</image_version>
</person>
Now, you can follow the following steps :
When the response arrives and you parse it, you initially create a new object from entity and fill the data directly.
Next time, when you perform an update on the server, you increase the version count of an entry by 1 and store it.
E.g. lets say the name michael is now changed to abraham, then version count of name_version on server will be 2
This updated version count will come in the response data.
Now, while storing the data in the same object, if you find the version count to be same, then the data update of that entry can be skipped, but if you find the version count to be changed, then the update of that entry needs to be done.
This way you can efficiently perform check on each entry and perform updates only on the changed entries.
Advice:
The above approach works best when you're dealing with large amount of data updation.
In case of simple text entries for an object, simple overwrite of data on all entries is efficient enough. And this also keeps the data reponse model simple.

Resolving conflicts between automated updates and manual overrides

This is a bit of a complex, abstract question, so forgive me if it's not specific enough.
I've encountered a specific type of problem numerous times: That on one hand, a data source is used to update a certain data structure in an automated fashion at regular intervals, but on the other hand, stakeholders want to be able to manually override the automated entries.
Example:
You have a list of products, which are kept up-to-date (title, description, etc.) by some automated script which uses external data sources (product databases, etc.).
Let's say that in your data source you have a toaster "Freshtoast XYZ 300" and if its name changes to "FreshToast! XYZ-300", you want to propagate that update into your own (differently structured) product model.
At the same time, if a co-worker doesn't like the name "Freshtoast XYZ 300" and wants to change it to "Toaster XYZ 300 by Freshtoast" (manually), you don't want to override that change automatically (he would get angry), but you also don't want to simply ignore the updated name, since if the co-worker knew about the change, he'd adjust the name to "Toaster XYZ-300 by FreshToast!".
What's the best method to "consider" updated data sources - even for overridden data - while still allowing manual override?
PS: I'm using mostly Ruby / Rails, but I guess the question is very general. Also, to be clear, automated updates are the rule, while manual overrides are the exception in this scenario. So let's say 200,000 products get updated every single day, only 20 of which have manually overridden titles. So, for example, having to approve every single update is not an option.
Here goes nothing...
Hands off approach: Add a string column to products table that contains a serialized list of user-touched columns. Anytime a user touches a column in the products table, put it in the serialized list. When the automatic updater hits that record it checks the list for columns it should ignore.
Hand-wringing micro-manager approach: Use a versioning library (e.g. vestal_versions gem) and add a user_id column to the products table. Anytime a user-touched record is automatically updated, send them a notification and allow them to view a before/after which they can approve or reject.

CAB file API clarification

Since I'm not really seeing any content anywhere that doesn't point back to the original Microsoft documents on this matter, or source code that really doesn't seem to answer the questions I'm having, I thought I might ask a few things here. (Delphi tag is there because that's what my dev environment is on the code I'm making from this)
That said, I had a few questions the API document wasn't answering. First one: fdi_notify messages. What is "my responsibility" is in coding these: fdintCABINET_INFO: fdintPARTIAL_FILE: fdintNEXT_CABINET: fdintENUMERATE: ? I'll illustrate what I mean by an example. For fdintCLOSE_FILE_INFO, "my responsibility" is to Close a file related to handle given me, and set the file's date and time according to the data passed in fdi_notify.
I figure I'm missing something since my code isn't handling extracting spanned CAB files...any thoughts on how to do this?
What you're more than likely running into is that FDICopy only reads the cab you passed in. It will use fdintNEXT_CABINET to get spanned data for any files you extract in response to fdintCOPY_FILE, but it only calls fdintCOPY_FILE for files that start on that first cab.
To get a directory listing for the entire set, you need to call FDICopy in a loop. Every time you get a fdintCABINET_INFO event, save off the psz1 parameter (next cab name). When FDICopy returns, check that. If it's an empty string you're done, if not call FDICopy again with the next cab as the new path.
fdintCABINET_INFO: The only responsibility for this is returning 0 to continue processing. You can use the information provided (the path of the next cabinet, next disk, path name, nad set ID), but you don't need to.
fdintPARTIAL_FILE: Depending on how you're processing your cabs, you can probably ignore this. You'll only see it for the second and later images in a set, and it's to tell you that the particular entry is continued from a previous cab. If you started at the first cab in the set you'll have already seen an fdintCOPY_FILE for the file. If you're processing random .cabs, you won't really be able to use it either, since you won't have the start of the file to extract.
fdintNEXT_CABINET: You can use this to prompt the user for a new directory for the next cabinet, but for simple spanning support just return 0 if the passed in filename is valid or -1 if it isn't. If you return 0 and the cab isn't valid, or is the wrong one, this will get called again. The easiest approach (if you don't request a new disk/directory), is just to check pfdin^.fdie. If it's FDIError_None it's equal the first time being called for the requested cab, so you can return 0. If it's anything else it's already tried to open the requested cab at least once, so you can return -1 as an error.
fdintENUMERATE: I think you can ignore this. It isn't covered in the documentation, and the two cab libraries I've looked at don't use it. It may be a leftover from a previous API version.

Resources