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.
Related
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.
I've noticed a few places in the Rails source code where module_eval is used. One place is in ActiveRecord::Enum and another is in ActiveRecord::Store. I'm familiar with class_eval and instance_eval and have used them for extending the functionality of existing classes or objects, but in the case of module_eval, it seems like it's serving a different purpose.
In both cases they are using a similar pattern to define the module:
def _store_accessors_module
#_store_accessors_module ||= begin
mod = Module.new
include mod
mod
end
end
If the module is being included in the class it's defined in, what benefit is there to defining related methods in a nested module like this? Is it better isolation of code? The reason I'm asking is because I have a gem that adds functionality to Active Record, and am wondering if this approach is more of a "best practices" way of doing the same thing. Here's the relevant source code of my gem for reference.
The reason the methods are being defined in a nested module is so that users may override the methods and still have access to super to get at the original functionality. Recall that when you include modules in Ruby they are inserted into the ancestors list for the current class and super works by simply iterating through the ancestors array, looking for the first object that responds to the current method. To this end, the name of the module is not important as it is simply an inheritance-chain-like delivery mechanism. So that's why they define just an anonymous new module and include it on the fly.
If you look at the blame view for the 2 examples you listed, you can see the reasoning behind the changes. The commit message in the ActiveRecord::Store example makes the case pretty well. As you can see, they're adding the ability to override the accessor definition color and tack on to the results of the original method via super || 'red'. Whereas, in the original implementation, one would have to both override the color accessor method and then do the same work as the original accessor method, i.e. call read_store_attribute(:settings, :color) || 'red'. So it's all about not being forced to reproduce the internals or using alias method chains to augment the functionality of the dynamically defined methods.
I'm not sure whether this is a useful feature in your gem, but I'm guessing maybe not as your accessors seem to be returning well-defined object enum-related objects. But, of course, that's up to you and the gem's users :).
How much of this is auto-generated methods in Rails "User.find_or_create_from_auth_hash(auth_hash)". That is just wondering how this works, and what would have been the minimum coding the dev would have to do? That is, what method would they have had to implement in the User model? or would they need a method named exactly that. So just wondering if the "find", "create", "from" keywords are Rails specials here.
Taken from here: https://github.com/intridea/omniauth
Rails provides the dynamic finders find_by_*, find_or_initialize_by_*, and find_or_create_by_* via method_missing for each attribute of your model.
The self.find_or_create_from_auth_hash(auth_hash) method however isn't at all provided by rails and is simply using the same type of naming conventions for readability.
EDIT:
Apparently it also provides find_last_by_* and find_all_by_* as well. I've personally never used them though.
I need to have two (or maybe even more) different create (and update) methods in one controller. I already have views displaying the forms, so I basicaly only need to tell the submit which method to call in the controller. Is that possible? If so, how? Or can I only have one create method and have that method do different things depending on which view called the method?
Thanks
Ignoring the fact that this sounds like a really terrible idea, it's possible. You will need to add some more routes that will match the new actions in your controller. You won't be able to call them 'create' and 'update' because method names must be unique within the same class.
Having said that, I really beg you to rethink your approach. REST, as described in the Rails Getting Started guide, by far the standard for building Rails applications. If you're not familiar with it, I would recommend stopping where you are and reading up on it. Your application will be much easier to build and maintain, and you won't waste time asking structural questions. If you are familiar with it and are choosing to ignore it, then I wish you the best of luck.
you can use this command:
rails g scaffold_controller 'controller_name'
or if spastic method you can use this:
rails generate controller 'controller_name' add new
Let's say that you have an object Book. You can change values of Book in any method inside of your books_controller.rb as long as that method has access to #book.id.
def crazy_create_method
book.create (book_params)
book.save
end
That being said, try to stick to the default new/create methods and if you need to get weird later on it's always easy to call the code belong in whatever method you need. Rails bakes a lot of out of the box functionality into the default REST actions.
book.title = my_title
book.save
I am using Ruby on Rails 3 and I am trying to use some custom method for an ActiveRecord so that I can do
Account.<my_method_name>
in order to add, for example, some data to the Account object (but without to change the Account data itself).
I heard of acts_as_<something> statement and it is used, if I am not wrong, on building plugins, but I didn't understand if it is what I need. After adding acts_as_<something> maybe I have to write somewhere a method like the following in order to "act" on the current ActiveRecord on which the <my_method_name> is called:
def self.<my_method_name>
...
end
Can someone explain me how to use that? And, if possible, can you make me a real example of its usage?
BTW: is it better to build a plugin or write a lib in the RAILS_ROOT/app/lib folder?
You can look at how to implement here => http://thoughtsincomputation.com/posts/coding-an-acts_as-gem-for-rails-3
For real example -> https://github.com/mbleigh/acts-as-taggable-on
The acts_as* is just way of adding behavior to a class. You can do the same by having a module ActsAs* and including this module in the class. Use the acts_as* only if you want to take arguments while adding this common behavior, otherwise just create a module and include it in the class
In the gem acts_as_taggable_on it makes sense because it takes arguments while adding the behavior.
acts_as_taggable_on :languages,:skills
You question is similar to rails3 gem: acts_as_something