How to check whether an instance of an ActiveRecord model is up to date? - ruby

For testing reasons, I want to check that one of my methods doesn't update a specific entry in my database. Is there a simple way to ask an instance of an ActiveRecord model if its in sync with the database? for instance, if we had a method foobar? that could do this:
old_post = Post.find(1)
updated_post = Post.find(1)
updated_post.update_attributes(name: "this is a new name not like the old name")
old_post.foobar? #should return true, as its attributes are no longer up to date
updated_post.foobar? #should return false, as its attributes match the database directly
So is there a method that acts like foobar, or something like it? Thanks in advance.

I think your problem lies beyond finding a method which tells you wether an attribute has been updated, but in the relationship among the different objects that are instantiated. First it is important to understand, that old_post and updated_post are unrelated ruby objects. They know about how to save their own state to the database, but they do not know about each other.
Therefore your first requirement for foobar? cannot be fulfilled, as old_post will think it is up-to-date as long as no attribute has been updated. In contrast the changed? method will roughly answer in the way you are trying to achieve for updated_post. However it does so because it thinks nothing has happened since it was last saved, this will not be verified against the database upon each call of changed? as this would be wasting a database call in 99.9% of all cases.
This means it is all too easy to generate anomalies between the objects you created as there is no direct connection between the two (except the implicit connection that they once represented the same database row). If you change an attribute in one object (using e.g. title='?' it will change the value of the object and take note of the change in the changed-array. Once you save this object it will save its changed attributes to the database (by creating an individually constructed update-statement).
Another object that is already instantiated (as old_post in your example) will not know about this change and might change other attributes if you are not careful (or even the same ones if they have been changed again). Depending on your database adapter you may try to use the lock! method which will synchronize your object with the database before allowing any modifications. This however will not happen automatically as in most controller methods updates do not conflict nearly often enough to merit the synchronization as it will be idempotent in most cases.
This does not go without saying that rails can not save you from thinking about your transaction semantics if you want to guarantee specific ACID semantics for your controller methods.

Related

Detect specific change during Eloquent Updated event

Using Eloquent Events/Observers, is it possible to detect which properties were updated within an Update event? Or, can you gain access to the previous/new values to do a comparison?
I'm finding the only solution is to manually fire events by detecting the specific field exists in the validated request data, in the controller.
Yes, absolutely. You can use the Model class's existing methods to gain access to various sets of data. The following methods should be helpful for what you want to do.
getChanges()
Get the attributes that were changed. (and saved)
$model->getChanges()
getOriginal()
Get the model's original attribute values.
$model->getOriginal()
getDirty()
Get the attributes that have been changed since last sync. (but not saved yet)
$model->getDirty()

ActiveRecord - prevent DB connection when calling Model.new

Every time I call Model.new, and before calling .save, ActiveRecord seems to get a database connection (which might make sense since it needs to get the field names).
How do I prevent this from happening? I don't intend to save the model into the database. I'm just creating it and then passing it to other functions.
Why don't you create a version of the model that doesn't inherit ActiveRecord::Base Then you can pass it around as a data object and leave your database alone until you actually need it.

Parameter validation vs property validation

Most (almost all?) validation frameworks are based on reading object's property value and checking if it obeys validation rules.
Do we really need it?
If we pass valid parameters into object's constructor, property setters and other methods, object seems to be perfectly valid, and property value checks are not needed!
Isn't it better to validate parameters instead of properties?
What validation frameworks can be used to validate parameters before passing them into an object?
Update
I'm considering situation where client invokes service method and passes some data. Service method must check data, create / load domain objects, do business logic and persist changes.
It seems that most of the time data is passed by means of data transfer objects. And property validation is used because DTO can be validated only after it has been created by network infrastructure.
This question can spread out into wider topic. First, let's see what Martin Fowler has said:
One copy of data lies in the database itself. This copy is the lasting
record of the data, so I call it the record state.
A further copy lies inside in-memory Record Sets within the application. This data
was only relevant for one particular session between the application
and the database, so I call it session state.
The final copy lies
inside the GUI components themselves. This, strictly, is the data they
see on the screen, hence I call it the screen state.
Now I assume you are talking about validation at session state, whether it is better to validate the object property or validate the parameter. It depends. First, it depends on whether you use Anemic or Rich Domain Model. If you use anemic domain model, it will clear that the validation logic will reside at other class.
Second, it depends on what type of object do you build. An Framework / operation /utility object need to have validation against object property. e.g: C#'s FileStream object, in which the stream class need to have valid property of either file path, memory pointer, file access mode, etc. You wouldn't want every developer that use the utility to validate the input beforehand or it will crash in one operation, and giving wrong error message instead of fail fast.
Third, you need to consider that "parameter can come in many sources / forms", while "class / object property only has 1 definition". You need to place the parameter validation at every input source, while object property validation only need to be defined once. But you also need to understand the object's state. An object can be valid in some state (draft mode) and not in other state (submission mode).
Of course you can also add validation into other state level as well, such as database (record state) or UI (screen state), but it also have different pros/cons.
What validation frameworks can be used to validate parameters before passing them into an object?
C#'s ASP.Net MVC can do one kind of parameter validation (for data type) before constructing into an object, at controller level.
Conclusion
It depends entirely on what architecture and kind of object you want to make.
In my experience such validations were done when dealing with complex validation rules and Parameter object. Since we need to keep the Separation of concerns - the validation logic is not in the object itself. That's why - yes we
we really need it
What is more interesting - why construct expensive objects and later validate them.

Code first validation that requires database access (duplicate valies)

This question may have already been asked, sorry
I'm looking at the architecture for validating our model. Our simple validation can be achieved by using the property validation attributes (some custom) and using
ModelState.IsValid
however the problem is when validation requires access to the database or access to another property. A perfect example is to check for duplicate names. In this case we need to check the database for duplicate names where the id is not equal to that of the current object (for updates)
If we were to write this as an validation attribute to be applied to the name property this would cause to problems. Ome how do we get access to the database and two how would we get access to the id property.
So in conclusion. Is there any examples of good ways to architect a fix to this problem?
I spent some time exploring this today for a project I was working on and came to these conclusions.
It is not to bad to solve the how, much of it involves some reflection and using the validation context to inspect and access other properties of your model or using IValidationObject. The real question becomes is it okay to do validation that requires database interaction.
For one I was concerned about performance, in one particular case a validation made a query that returned an object to ensure it existed which I later needed for relationship assignment which would then cause another query.
Secondly you need to think about database concurrency. The best way to do duplication checks is during insert not before because the database could change between the two operations. This also relates to the first reason, an object could be deleted immediately after a database reported it exists.
In my particular project I felt it better to keep this sort of behavior with modifying my EF context and adding anything that went wrong to the ModelState.

Linq To Sql Where does not call overridden Equals

I'm currently working on a project where I'm going to do a lot of comparison of similar non-database (service layer objects for this discuss) objects and objects retrieved from the database via LinqToSql. For the sake of this discussion, assume I have a service layer Product object with a string field that is represented in the database. However, in the database, there is also a primary key Id that is not represented in the service layer.
Accordingly (as I often do for unit testing etc), I overrode Equals(Object), Equals(Product), and GetHashCode and implemented IEquatable with the expectation that I would be able to write code like this:
myContext.Products.Where(p => p.Equals(passedInProduct).SingleOrDefault();
And so forth.
The Equals override is tested and works. The objects are mutable so the usual caveats apply to the GetHashCode override. However, for the purposes of this example, the objects are not modified except by LtS and could be made readonly.
Here's the simple test:
Create a test object in memory and commit to the LtS context. By committing, the test object is populated with a few auto-generated fields.
Create another identical test object in memory (separate reference)
Attempt to retrieve the first object from the database using the second object as the criteria. (see code line above).
// Setup
string productDesc = "12A";
Product testProduct1 = _CreateTestProductInDatabase(productDesc);
Product testProduct2 = _CreateTestProduct(productDesc);
// check setup
Product retrievedProduct1 = ProductRepo.Retrieve(testProduct1);
//Assert.IsNotNull(retrievedProduct1);
// execute - try to retrieve the 'equivalent' product object
Product retrievedProduct2 = ProductRepo.Retrieve(testProduct2);
A simplified version of Retrieve (cruft removed is just parameter checks etc):
using (var dbContext = new ProductDataContext()) {
Product retrievedProduct = dbContext.Products
.Where(p => p.Equals(product)).SingleOrDefault();
NB: The overridden Equals method knows not to care about the auto-generated fields from the database and only looks at the string that is represented in the service layer.
Here's what I observed:
Retrieve on testProduct1 succeeds (no surprise, equal by reference)
Retrieve on testProduct2 fails (null)
The overridden Equals method called in the Retrieve method is never hit during either Retrieve calls
However, the overridden Equals method is called multiple times by the context on SubmitChanges (called when creating the first test object in the database) (works as expected).
Statically, the compiler knows that the type of the objects being emitted and is able to resolve the type.
So my specific questions:
Am I trying to do something ill-advised? Seems like a straightforward use of Equals.
Corollary to first question: alternate suggestions to deal with linq to sql equality checking while keeping comparison details inside the objects rather than the repository
Why might I have observed the Equals method being resolved in SubmitChanges but not in the Where clause?
I'm as much interested in understanding as making my Equals calls work. But I also would love to learn how to make this 'pattern' work rather than just understand why it appears to be an 'anti-pattern' in the contest of LtS and C#.
Please don't suggest I just filter directly on the context with Where statements. Obviously, I can remove the Equals call and do that. However, some of the other objects (not presented here) are large and a bit complicated. For the sake of maintenance and clarity, I want to keep knowledge of how to compare itself to another of its own type in one place and ideally as part of the object in question.
Some other things I tried that didn't change the behavior:
Overloaded and used == instead
Casting the lambda variable to the type p => (Product)p
Getting an IQueryable object first and calling Equals in the Where clause
Some other things I tried that didn't work:
Creating a static ProductEquals(Product first, Product second) method: System.NotSupportedException:has no supported translation to SQL.
Thanks StackOverflow contributors!
Re Possible dups: I've read ~10 other questions. I'd love a pointer to an exact duplicate but most don't seem to directly address what seems to be an oddity of LinqToSql.
Am I trying to do something ill-advised?
Absolutely. Consider what LINQ to SQL does: it creates a SQL representation of your query. It doesn't know what your overridden Equals method does, so can't translate that logic into SQL.
Corollary to first question: alternate suggestions to deal with linq to sql equality checking while keeping comparison details inside the objects rather than the repository
You'd need to do something with expression trees to represent the equality that way - and then build those expression trees up into a full query. It won't be fun, but it should be possible. It will affect how you build all your queries though.
I would have expected most database representations to be ID-based though, so you should be able to just compare IDs for equality. Usually when I've seen attempts to really model data in an OO fashion but store it in a database, the leakiness of the abstraction has caused a lot of pain.
Why might I have observed the Equals method being resolved in SubmitChanges but not in the Where clause?
Presumably SubmitChanges is working against a set of in-memory objects to work out what's changed - it doesn't have to do any conversion to SQL to do that part.

Resources