Sometimes I'm required to keep track of whether an activerecord object was succesfully saved.
A case in point would be doing something in an after_filter of a controller. For example, I might want to keep track of how many times users post invalid active records.
One way of doing this would be to use #valid?, but this will hit the database again in some cases (e.g. if there's a validates_uniqueness_of), which I want to avoid.
On a past project where we wanted something like an after_filter to
check whether the user input was valid, it just looked at
@whatever.errors.empty? to avoid rerunning the validations. Obviously
that makes assumptions about what the action has done, but I think
they're the same assumptions you'd have to make to use your API.
That seems like a good idea for an application that needs to track
that in a few places, but I'd rather see it stay in a plugin than
become part of core. It seems to crowd the API a bit, and adds
something not many people need.
I could see people getting confused by the following, thinking #saved?
should be the opposite of #new_record?.
t = Thing.find(:first)
t.new_record? # => false
t.saved? # => nil
puts "But it's in the database! It is sooo saved!"
If people like this feature, I'd like to see #saved? renamed to reduce
the likelihood of the above. Maybe "instance_saved?" is better, but I
can still imagine people not grokking it until it's bitten them.
On a separate note, I think it's surprising to have a predicate method
return nil.
Sometimes I'm required to keep track of whether an activerecord object
was succesfully saved.
A case in point would be doing something in an after_filter of a
controller. For example, I might want to keep track of how many times
users post invalid active records.
One way of doing this would be to use #valid?, but this will hit the
database again in some cases (e.g. if there's a
validates_uniqueness_of), which I want to avoid.
The point here is to be able to use that in a filter, since otherwise you do
if model.save
# saved
end
In my view the definition of the predicates is going to depend on your
particular needs. If you save and change an attribute in the next line
what should the flags say? I don't really see it in the core API.
If you save and change an attribute in the next line
what should the flags say?
.saved? should be true - I'm just proposing something pretty simple (what was the result of the last #save ?)
Jack Christensen wrote:
!(model.new_record? || model.changed?)
This is great idea - it doesn't work for the reload case, but I don't think it needs to for the controller case
John D. Hume wrote:
it just looked at @whatever.errors.empty?
This also works great - and you can use the existence of the @errors var to find if a save (or validation) has been attempted.
(Also doesn't work for the reload case)
However, making #saved? depend on the existing internals would be a bad idea in my view, because it'd so much
clearer, and less prone to break if these other things change in implementation, to just have an instance variable tracking this
But I take your point on the semantics of saved? - it should be called #instance_saved?, in which case it's fugly and seems to show
that it probably shouldn't be in the API
Summarizing:
You can already do (most of) this, using ARs state. And it's a bit undermotivated when fleshed out. So keep as a plugin, if it's required at all.
Thanks very much for the input guys! - Saved me cluttering up lighthouse.