I have a simple model in RoR and I would like to keep eveything people enter on the site. But I also want to be able to hide some content if the user click on "Remove".
So I added a bolean attribute in my model called "displayed".
I would like to know, what would be the best-practices-styled method.
I guess I have to change the controller with something like :
def destroy
@point = Point.find(params[:id])
@point.displayed = false
@point.save
respond_to do |format|
format.html { redirect_to points_url }
format.json { head :no_content }
end
But I am not sure it is clean. What would be the best way to do it.
As you guess I am noobish with RoR. Chunks of code would be appreciated.
Thank you
Implement it yourself (rather than using a gem). It's much, much easier than it seems at first, and it's less complex than any of the gems out there that change the meaning of the destroy
method, which is a bad idea, in my opinion.
I'm not saying that using the gems themselves are complex - I'm saying that by changing the meaning of the destroy
method you're changing the meaning of something that people in the Rails world take for granted - that when you call destroy
that record is going to go away and that destroy
maybe also be called on dependent objects if they are chained together via dependent: destroy
callbacks.
Changing the meaning of destroy
is also bad because in the "convention over configuration" world, when you screw with conventions you're essentially breaking the "automagic-ness" of your Rails code. All that stuff you take for granted because you read a piece of Rails code and you know that certain assumptions generally apply - those go out the window. When you change those assumptions in ways that aren't obvious you're almost certain to introduce a bug down the line because of it.
Don't get me wrong, there's nothing better than actually reading the code for checking your assumptions, but it's also nice, as a community, to be able to talk about certain things and generally have their behavior act in a certain way.
Consider the following:
destroy
action in the controller, so don't. It's one of the standard actions, but it's not required.update
action to set and clear an archived
boolean attribute (or something similarly named)acts_as_paranoid
gem, and if you need to add any scopes to your models (other than the ones the gem provides) you're going to find yourself having to hack your way around it, turning off the default "hide archived records" scope, and when you run into that it almost immediately loses its value. Besides, that gem does almost nothing on its own, and its functionality could easily be written yourself (and I mean barely more work than installing the gem itself), so there's really no benefit to using it from that perspective.destroy
method or action is a bad idea because it breaks the Rails (and ActiveRecord) convention as to what it means to call destroy
on an object. Any gem that does this (acts_as_paranoid
for example) is also breaking that convention, and you're going to wind up confusing yourself or someone else because destroy
simply won't mean what it's supposed to mean. This adds confusion, not clarity to your code. Don't do this - you'll pay for it later.before_destroy
callback and simply return false, which will prevent it from being destroyed at all unless an explicit call to delete
is used (which isn't the same as destroy anyway). Also, having the callback in place makes it (a) really obvious why destroy
doesn't work without changing its meaning, and (b) it's easy to write a test to make sure it's not destroyable. This means in the future, if you should accidentally remove that callback or do something else that makes that model destroyable, then a test will fail, alerting you to the situation.Something like this:
class Point < ActiveRecord::Base
def archive
update_attribute!(:displayed, false)
end
end
And then call @point.archive
in the destroy action of your controller where you would normally call @point.destroy
. You can also create a default_scope
to hide archived points until you explicitly query for them, seethe RoR guide on appling a default scope.
Edit: Updated my answer as per normalocity & logan's comments below.
Look at the acts_as_archive gem. It will do soft deletes seamlessly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With