IIRC with Rails 4 associations introduce their methods via a module, which means you can super
to them, so why not:
class Post
has_many :comments
def comments(*)
super.visible
end
end
I’m not too keen on having moar DSL when defining a simple method suffices. It also gives you more flexibility to call whatever on the association.
For example, your suggestion to avoid an Array of scopes is to define an extra scope / singleton method on Comment for the sole purpose of having something you can call here. But then you’re defining a method on Comment that you only use from Post, which is weird (and potentially confusing—later one someone might change the scope passed to the association, but might not know that the scope definition on Comment is no longer used, so you end up with dead code).
With this approach you can simply call whatever you want on the method overriding the association, instead of having to do extra work just for the sake of having a DSL.
Cheers,
-foca
foca, in your example, I’d use Post.find(1).comments to get only the visible comments. How would I be able to get ALL the comments, including the hidden ones? I’m thinking of passing a parameter to the comments method.
class Post
has_many :comments
def comments(show_hidden = false)
show_hidden ? super : super.visible
end
end
Is this the right way?
The problem with that is that you’re overloading the meaning of association(flag). When passing a boolean to an association, you are telling it to force-reload the association (if true). If I read in the code “post.comments(true)” I will always think you’re trying to force-reload the association, which would be weird 
If you want to have both versions of the association (with and without the scope), I would just define a different method (visible_comments
).
There’s also a subtle bug with your code: The version of super without parentheses will invoke the superclass method with the same arguments than the current method, which would pass the boolean flag to the association per-se, which would have weird effects (since you’d force an extra query every time you try to load the visible comments).
You would need to call super() like so:
def comments(show_hidden = false)
show_hidden ? super() : super().visible
end
Cheers,
-foca
Ah-ha! Didn’t think of the super-without-paranthesis bug! Very subtle, good catch!