Rails proper way to distinguish methods from variable names? - ruby-on-rails

Now that my controllers are expanding beyond the basic REST actions it can get somewhat confusing as to whether a given expression is either a built in method, a controller method, from the model, or a variable.
Would adding empty parentheses to my controller methods when I call them from other methods cause any problems down the road? Like so:
if customer.save?
subscription_checker()
end
I'm at least trying to always use an underscore in the names of the methods I create in order to make them look different from most of the built in methods.

Would adding empty parentheses to my controller methods when I call them from other methods cause any problems down the road?
This is a valid way to distinguish between variables vs methods in ruby, but "You're Doing It Wrong" ™
Part of the ruby paradigm is that you shouldn't typically care whether the thing you're referencing is a variable or a method. This makes the code easier to read and refactor; keeping the developer's attention focused on code's intent rather than its implementation.
This design pattern is often referred to as "bare words", and I highly recommend the following RubyTapas episode on the subject: http://www.virtuouscode.com/2012/10/01/barewords/
I would also recommend that you have a quick read through a ruby style guide, to see what common conventions are considered "good" or "bad" by the community. (Ruby code styles are extremely well conformed to by the community!) For example, from this guide:
Only omit parentheses for
Method calls with no arguments:
# bad
Kernel.exit!()
2.even?()
fork()
'test'.upcase()
# good
Kernel.exit!
2.even?
fork
'test'.upcase
In your particular code above, although it's hard to say for sure without knowing more context, I suspect that subscription_checker should actually be abstracted into a separate class rather than yet-another-method in the controller. But as I say, in order to give any concrete advice here I'd need to see more of the source file this is taken from.

Related

How can I ensure a reserved word will not conflict with Ruby, Rails 4, or a gem in my gemlist

I have a Rails4 application to which I want to add a model named 'Parameters' It's a good choice in terms of the models purpose, but I worry that it is also a common programming term.
What is the best practice (individual steps) to ensure that:
Parameters
parameter.thing
... will not conflict with a reserved word in Ruby, Rails, or my particular Gem list?
Ruby has a concept of open classes. That said, when the class MyClass is defined somewhere, it’s perfectly valid to have the following in your code:
class MyClass
def another_method
# do something useful
end
end
That said, there is no “reflection-like” mechanism for this action, since it is how Ruby is intended to work.
One might build the complicated logic like this:
run the application without new Parameters class loaded;
call $defined = const_get('Parameters') || true rescue false;
use $defined global (it’s made global here for the sake of an example) to determine whether the name is free.
or:
use TracePoint#new(:class) on Parameters to detect whether only yours was loaded.
or
use ObjectSpace#each to detect other classes.
or even
parse sources.
But I would not go with any of solutions above. Just call your class MyAppParameters and live with this name.
An IDE like RubyMine should warn you by coloring the text whenever you use a reserved word, but for people like me who use glorified text editors, you can always check this list of Rails related reserved words when you're not sure.

break away from a controller action

My question is if there is a rails equivalent to 'breaking' away from a controller action such as
def new
if some_confirmation
do_stuff
break #I know this only breaks out of a loop but I want it to break out of the action. is this possible?
end
do_some_other_stuff_which_it_should_not_reach_after_breaking
end
Also this raises the question if I'm doing something wrong and shouldn't be rather doing it with a before_filter
Also last question, is it better to enclose everything in a 'if-else'-statement in such definitions (not necessarily controller actions but also normal definitions) or do it like the way I intend to do up there ^?
The answer is to use return. Controller actions are just methods and return is how you return early from a method. There's nothing wrong with doing this and you should feel free to do so as needed.
You can use before_filters (which has been renamed to before_action in Rails 4), as you mention, but I recommend only doing this if every method in the controller requires the condition. Otherwise, you end up with a huge list of before_actions at the top that you have to keep in mind (or be surprised by) while reading the actions later; and it gets especially confusing if you have to keep in mind which ones apply and which ones don't for which actions!
Whether or not if-else statements are preferred is a bit of an opinion... but, inspired by Avdi Grimm's excellent book Confident Ruby, I recommend to do as you've done here... what you've set up is essentially a guard clause whereby you take care of exiting the method early up front, and then you get into the actual meat of the method. In Confident Ruby, Avdi Grimm talks about breaking methods up into logical parts to tell a coherent story that doesn't force readers to keep track of various states throughout the life of the method. Using an if-else statement tends to force readers to keep track of state, whereas using guard clauses allows you to quickly identify conditions to leave the method via and then forget about them so you can focus on the actual purpose of the method.

Rails: Ruby Code That Can Scan Ruby Code

I'm starting a project with several contributors. We want to keep track of who wrote what code, as well as to get a count of how many methods, controller actions, and views a contributor has written. This necessitates a level of meta-programming that none of us are familiar with.
So far, the best idea we've come up with is to add a comment before each snippet of code with the contributor's username and a short, consistent phrase. For instance:
# method by RacerX
def a_useful_method
. . .
end
# method by MysteryProgrammer123
def another_useful_method
. . .
end
# action by MysteryProgrammer123
def new
. . .
end
Then we'd run a method to count all instances of action by and method by and view by that each user has written throughout the project. Unfortunately, we don't know how to write Ruby code that can inspect other Ruby code. It might not even be possible. If it is possible, though, how is it done?
Alternatively, there might be a better approach that we're not considering.
You should prefer your source control system to track who wrote what. git blame, for instance, can produce an annotated listing showing author and source line.
Identifying views should be easy, they're in the view directory. Static method definitions can generally be found with regexp /\bdef\s+(?:\w+\.)?(\w+)\b/. Distinguishing "actions" from other methods probably involves filtering method names against common action names and other names discovered by examining your routes.
Rather than reinventing the wheel, use a ready-made tool. And if it does not come to your mind how to implement such code, then you probably will not be able to write such code. A documentation tool such as YARD may be useful. The way this works is that you add explanations as comments before method definitions. Usually this is for writing the documentation to be read by the users, but you can depart from its intended use and write things like the programmers name, or whatever other information you like.

I18n: What is the difference between using 't(:test_key)', 't('test_key')' and 't('.test_key')'?

I am using Ruby on Rails 3.1 and I would like to know how, when and why I should use one of the following code rather than another on internationalizing my application (I18n gem):
t(:test_key)
t('test_key')
t('.test_key')
That is, what is the "subtle" difference between using t(:test_key), t('test_key') and t('.test_key')? What are best practices about this issue?
I think first two are equivalent and you just refer to main key in your translations, fo example
t('hello_world')
# t(:hello_world) is an equivalent
would reffer to
en:
hello_world: "Hello world"
However if you use dot notation, its called lazy lookup
and it will look deeper in your translation structure based on controller/action notation
So if you use this inside users/index template
t('.hello_world')
it will be resolved to
pl:
users:
index:
hello_world: "Witaj świecie"
You'll find more about internalization in Rails Guides
I guess it's a but up to you to decide when you actually want to use the different ones, but I'd prefer to use lazy lookup as much as possible in my views, unless you need to translate some generic component whose keys does not live in the scope of your view.
The reason why I prefer the lazy lookup is that it makes the code look cleaner, and as long as you're familiar with how the i18n gem works, you shouldn't have any trouble knowing where to look for the keys.
On the other hand, if you have such components, they should really live in a partial, a cell or something similar.
One thing worth mentioning abouth the non-lazy ones, are that you can provide them with a scope for where to look for the key in question. Again, it's up to you whether you like t('foo.bar.baz.test_key') or t(:test_key, :scope => 'foo.bar.baz').
It also takes a bunch of other options, but all of this is neatly documented in the rails guide, so I won't explain it further here.

DRY Rails Metaprogramming - Use Cases

So I've running around my app, applying this particular use case for DRY'ing your app via metaprogramming:
http://rails-bestpractices.com/posts/16-dry-metaprogramming
In what other ways are you applying metaprogramming to keep your app DRY?
I wrote a gem called to_lang which makes use of this type of dynamic method definition. It adds a bunch of methods to strings in the form to_language which all call a single method with different parameters. ToLang::StringMethods in particular is where this magic happens. Doing the same thing without metaprogramming would require the definition of hundreds of methods.

Resources