Why can't I call an ActionView method from the Rails Console? - ruby-on-rails

I'm trying to do a little testing of the number_to_currency method, but no matter how I try and call it in the console I'm out of luck it seems.
ActionView::Helpers::NumberHelper::number_to_currency 12321334543.00
# => NoMethodError: undefined method `number_to_currency' for ActionView::Helpers::NumberHelper:Module
This may qualify as a duplicate, I am not entirely sure. The other question is a lot broader in scope, and therefore has a lot more ways of getting things gone presented in the answers, and I also believe it may have some outdated answers.

ActionView::Helpers::NumberHelper is a module. Whenever you want to use it you should include it and all it's method could be used after that. So the first step is including ActionView::Helpers::NumberHelper module:
include ActionView::Helpers::NumberHelper
and then call the method you want:
number_to_currency 12321334543.00
Take a look at Ruby modules tutorial.
Edit:
Getting a console session bootstrapped with Rails’ helpers is also a pain, which helper can fix for you! You could also use it to play with building HTML tags, or any existing Rails helper that ActionView knows about (checkout this blog post).
helper.number_to_currency 12321334543.00

try helper.number_to_currency 12321334543.00

Related

Testing Rails helper that uses html escaping

I'm attempting test a helper in Rails 4 that calls h(some_content) but when I run my unit tests I receive: undefined method 'h' for PageHelperTest.
How can I call h inside my helper, but still be able to execute the code in test? The code works correctly when hit through the website.
The h method is defined on ERB::Util which isn't available in the helper test. I fixed the issue by changing the helper to call ERB::Util.h(some_content)
Well I just hit similar issue.
However changing the helper just for the tests to pass is a NO NO to me.
So I tried around and this solved it (HOWEVER in Rails 3.2.22):
include ERB::Util
alias_method :html_escape, :h
I guess it's not the cleanest way (the alias, and what if another helper needs some other thing). So I guess there would be some better way (include some group of modules or whatnot) - but this one works.

Rails get url_for working inside model

Title says it all. It's pretty easy from controllers - just using "view_context". But it doesn't work with models.
E.g ApplicationController.new.view_context.url_for yields in: "undefined method 'host' for nil:NilClass"
ActionView::Base.new(Rails.configuration.paths["app/views"].first).url_for doesn't work as well.
Can this be done without so much pain ?
P.S I need it for my Prawn gem! I wanted to generate the PDF from the model. And apart from generating the links inside of it - it is very successful!
Hope for your help! Thanks in advance!
Rails 5
include Rails.application.routes.url_helpers
url_for(myModelObject)
It might depend on Rails version, but generally this method is now defined in Rails.application.routes. It expects you to provide hash with url_options, with :host key among others.

Ruby on Rails - Reload Class Cache on Demand

Does Ruby on Rails 3 (3.0.7) offer a mechanism to reload the class cache on demand? I am running some tests where I overwrite some methods in ApplicationController and in some of my models to stub out authentication. For example, I call a method (I'm using Cucumber for testing) in some of my tags (Before('#tag')) that does this:
ApplicationController.send(:define_method, :current_user) do
#current_user ||= User.where(:id => cookies[:user_id]).first
end
...where the actual current_user method in ApplicationController has a different behavior.
This works great until I need to run some tests in which I do not want to stub out those methods. With config.cache_classes = true set in my test environment, ApplicationController is not reinitialized without my monkey patch, making the tests I don't want to stub out fail. With config.cache_classes = false, my monkey patch is forgotten on the next request, causing all of the tests that I need to stub to fail.
Ideally, I would like to be able to erase the class cache in an After('#tag') method, if this is possible. How can I accomplish that? Or is there a better way of stubbing out certain methods in certain scenarios that I am overlooking?
You could take inspiration from this great SO answer, and make good use of ActionDispatch::Callbacks.
ActionDispatch::Reloader.cleanup!
ActionDispatch::Reloader.prepare!
I posted the rationale behind this over here: Why does code need to be reloaded in Rails 3?
If its bad to cross post the same answer, kindly let me know how its preferred to post an answer thats relevant to two questions...I'm happy to oblige.
As of newer Rails (> 4.0), I was able to reload class definitions, in console, for instance, with reload!.

nest helper methods in rails3

I would to nest some helper methods to simplify my application_helper, for example I have a bunch of methods dealing with currencies which apply for the entire app and I would like to put in the currencies_helper and then simply include that entire helper into the application helper.
How can I do this?
I tried:
helper :currencies
and got
undefined method `helper' for ApplicationHelper:Module
Helpers in rails are just modules which get included in controllers to help share functionality between them. There's been some weirdness around helpers in rails 3, so depending on what version you're running things may or may not work as you expect out the box.
Essentially what you want to do is add helper :all to your application_controller which will include ALL helpers in ALL your controllers. If this isn't what you want you can specify the specific helpers you want helper :currencies for example.
In the rails 3 betas helper :all was the default behavior, but I think they've reverted that in the latest release.
There's a great article that discusses how this works in rails 2, but there may be differences in rails 3, but it should be a good starting point.

Ruby on Rails: alias_method_chain, what exactly does it do?

I've tried reading through various blog posts that attempt to explain alias_method_chain and the reasons to use it and not use it. In particular, I took heed to:
http://weblog.rubyonrails.org/2006/4/26/new-in-rails-module-alias_method_chain
and
http://yehudakatz.com/2009/03/06/alias_method_chain-in-models/
I still do not see any practical use for alias_method_chain. Would anyone be able to explain a few things.
1 - is it still used at all?
2 - when would you use alias_method_chain and why?
1 - is it still used at all?
Apparently yes, alias_method_chain() is still used in Rails (as of version 3.0.0).
2 - when would you use
alias_method_chain and why?
(Note: the following is largely based on the discussion of alias_method_chain() in Metaprogramming Ruby by Paolo Perrotta, which is an excellent book that you should get your hands on.)
Let's start with a basic example:
class Klass
def salute
puts "Aloha!"
end
end
Klass.new.salute # => Aloha!
Now suppose that we want to surround Klass#salute() with logging behavior. We can do that what Perrotta calls an around alias:
class Klass
def salute_with_log
puts "Calling method..."
salute_without_log
puts "...Method called"
end
alias_method :salute_without_log, :salute
alias_method :salute, :salute_with_log
end
Klass.new.salute
# Prints the following:
# Calling method...
# Aloha!
# ...Method called
We defined a new method called salute_with_log() and aliased it to salute(). The code that used to call salute() still works, but it gets the new logging behavior as well. We also defined an alias to the original salute(), so we can still salute without logging:
Klass.new.salute_without_log # => Aloha!
So, salute() is now called salute_without_log(). If we want logging, we can call either salute_with_log() or salute(), which are aliases of the same method. Confused? Good!
According to Perrotta, this kind of around alias is very common in Rails:
Look at another example of Rails
solving a problem its own way. A few
versions ago, the Rails code contained
many instances of the same idiom: an
Around Alias (155) was used to add a
feature to a method, and the old
version of the method was renamed to
something like
method_without_feature(). Apart from
the method names, which changed every
time, the code that did this was
always the same, duplicated all over
the place. In most languages, you
cannot avoid that kind of duplication.
In Ruby, you can sprinkle some
metaprogramming magic over your
pattern and extract it into its own
method... and thus was born
alias_method_chain().
In other words, you provide the original method, foo(), and the enhanced method, foo_with_feature(), and you end up with three methods: foo(), foo_with_feature(), and foo_without_feature(). The first two include the feature, while the third doesn't. Instead of duplicating these aliases all around, alias_method_chain() provided by ActiveSupport does all the aliasing for you.
alias_method_chain has been deprecated in Rails 5 in favour of Module#prepend.
Pull request: https://github.com/rails/rails/pull/19434
Changelog: https://github.com/rails/rails/blob/b292b76c2dd0f04fb090d49b90716a0e6037b41a/guides/source/5_0_release_notes.md#deprecations-4
I'm not sure if it's gone out of style with Rails 3 or not, but it is still actively used in versions before that.
You use it to inject some functionality before (or after) a method is called, without modifying any place that calls that method. See this example:
module SwitchableSmtp
module InstanceMethods
def deliver_with_switchable_smtp!(mail = #mail)
unless logger.nil?
logger.info "Switching SMTP server to: #{custom_smtp.inspect}"
end
ActionMailer::Base.smtp_settings = custom_smtp unless custom_smtp.nil?
deliver_without_switchable_smtp!(mail = #mail)
end
end
def self.included(receiver)
receiver.send :include, InstanceMethods
receiver.class_eval do
alias_method_chain :deliver!, :switchable_smtp
end
end
end
That's an addition to ActionMailer to allow swapping out of the SMTP settings on each call to deliver!. By calling alias_method_chain you are able to define a method deliver_with_switchable_smtp! in which you do your custom stuff, and call deliver_without_switchable_smtp! from there when you're done.
alias_method_chain aliases the old deliver! to your new custom method, so the rest of your app doesn't even know deliver! now does your custom stuff too.
is it used at all?
Seems so. It's a common practice among Rails developers
when would you use alias_method_chain and why?
Despite the warnings, alias_method_chain is still the main strategy used when injecting functionality to an existing method, at least was in Rails 2.x and is followed by many people extending it. Yehuda ought to remove alias_method_chain from rails 3.0 to say from his posts and comments in Rails tickets. It is still used by many extensions that add custom behavior at certain points of the execution, such as loggers, error reporters, benchmarking, data injection, etc.
IMO, the best alternative is to include a module, thus you have decoration over delegation. (For example, follow example 4 in this post). That way you can alter the objects even individually if you'd like, without polluting the class' methods. The downside to this is that the method lookup chain increases for each module you inject, but this is what modules are for anyway.
Very interesting question, will keep a look on what other people think about it.

Resources