# | |
# If you want to use helper methods inside your controller's actions | |
# (even though it is arguably a code smell, ie you should push your | |
# presentation logic down into views rather than have it in your | |
# controllers), you can include the helper modules you want, for | |
# example: | |
# | |
# class ThingController < ActionController::Base | |
# include ApplicationHelper | |
# include ThingHelper | |
# ... | |
# end | |
# | |
# But this will pollute your controller with all the methods from the | |
# helpers which might be undesirable. | |
# | |
# There are various workarounds for this, such as: | |
# * http://www.johnyerhot.com/2008/01/10/rails-using-helpers-in-you-controller/ | |
# * http://snippets.dzone.com/posts/show/1799 | |
# * http://masonoise.wordpress.com/2010/01/16/using-rails-tag-helpers-in-a-controller/ | |
# | |
# You can also access any helper from a controller action using something like | |
# this: | |
# | |
# ActionController::Base.helpers.some_helper | |
# ThingController.helpers.some_helper | |
# | |
# or even this (?) | |
# | |
# self.class.helpers.other_helper | |
# | |
# but that fairly inconvenient and awkward looking, so let's make it nicer. | |
# | |
# This defines the use_helper_method which can be used as follows: | |
# | |
# class ThingController < ActionController::Base | |
# use_helper_method :some_helper, :other_helper | |
# ... | |
# def some_action | |
# ... | |
# @message = "Hello #{some_helper(@thing)}\n\nRegards #{other_helper(@user)}" | |
# end | |
# end | |
# | |
# It will create a private method in your controller that just calls | |
# the helpers you specified. Now you can call some_helper and pluralize | |
# directly from your action methods. | |
# | |
# (Not to be confused with ActionController::Base.helper_method and | |
# ActionController::Base.helper which do very different things...) | |
# | |
# Note: This is kind of experimental. There might be a better way to | |
# do it. | |
# | |
class ActionController::Base | |
def self.use_helper_method(*syms) | |
syms.each do |helper_method| | |
class_eval <<-EOM | |
private | |
def #{helper_method}(*args) | |
self.class.helpers.#{helper_method}(*args) | |
end | |
EOM | |
end | |
end | |
end |
Monday, October 3, 2011
Another approach to using helper methods in your controller actions in Ruby on Rails
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Tuesday, September 20, 2011
A Rails 3 gotcha with html_safe
This was causing me to scratch my head a bit today. I'm glad I know what's going on now and why you need to use safe_concat. It still seems a little unintuitive though.
For more into see the explanation here (under the "the tricky part") and the api docs on ActiveSupport::SafeBuffer
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# This is pretty confusing until you know what's going on... | |
# | |
# See http://techspry.com/ruby_and_rails/html_safe-and-helpers-in-rails-3-mystery-solved/ | |
# for an explanation... | |
# | |
ruby-1.8.7-p334 :025 > foo_safe = "<p>foo</p>".html_safe | |
=> "<p>foo</p>" | |
ruby-1.8.7-p334 :026 > (foo_safe + "<p>bar</p>").html_safe # not what you thought! unintuitive! | |
=> "<p>foo</p><p>bar</p>" | |
ruby-1.8.7-p334 :027 > "#{foo_safe}<p>bar</p>".html_safe # I think it works because of the implicit to_s | |
=> "<p>foo</p><p>bar</p>" | |
ruby-1.8.7-p334 :028 > foo_safe.safe_concat("<p>bar</p>") # correct, but looks pretty clunky, right? | |
=> "<p>foo</p><p>bar</p>" |
My (first) contribution to Rails
I fixed a little mysql configuration bug in Rails. It counted as three commits (even though they are the same thing, just in different branches), which puts me unfairly into the top 500 all time committers. ;) See here.
You'd think DHH would be number one, but actually he's not. Take a look at the list.
Here is my original pull request if you'd like to read more about it.
Ps, I also reported a capybara bug (along with a failing test) that got fixed pretty quickly. But my fork didn't get merged so none of my commits are recorded. :P
You'd think DHH would be number one, but actually he's not. Take a look at the list.
Here is my original pull request if you'd like to read more about it.
Ps, I also reported a capybara bug (along with a failing test) that got fixed pretty quickly. But my fork didn't get merged so none of my commits are recorded. :P
Friday, June 17, 2011
Tau in Ruby
Inspired by http://bugs.python.org/issue12345 and of course The Tau Manifesto, here is a patch for ruby to define tau, the true circle constant.
Of course we don't need to really need to patch ruby to get this functionality (but I had fun doing it anyway).
Here is tau.rb so you can just require 'tau'. (Maybe this should be a gem...)
Ps, I just learned about module_function.
Update 1: I made this ticket which has been mostly ignored.
Update 2: Ticket has been noticed and discussed! :) Ticket has been categorised as joke! :(
Update 3: Some active debate is going on now and the ticket is now 'assigned'! :) See the details.
Update 4: (28-Jun-2014) Made a pull request in Github.
Update 5: See https://github.com/jneen/math-tau/
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/ext/bigdecimal/lib/bigdecimal/math.rb b/ext/bigdecimal/lib/bigdecimal/math.rb | |
index c17841f..c672cbf 100644 | |
--- a/ext/bigdecimal/lib/bigdecimal/math.rb | |
+++ b/ext/bigdecimal/lib/bigdecimal/math.rb | |
@@ -9,6 +9,7 @@ require 'bigdecimal' | |
# atan(x, prec) Note: |x|<1, x=0.9999 may not converge. | |
# exp (x, prec) | |
# log (x, prec) | |
+# TAU (prec) | |
# PI (prec) | |
# E (prec) == exp(1.0,prec) | |
# | |
@@ -222,6 +223,11 @@ module BigMath | |
y | |
end | |
+ # See http://tauday.com/ | |
+ def TAU(prec) | |
+ PI(prec)*BigDecimal("2") | |
+ end | |
+ | |
# Computes the value of pi to the specified number of digits of precision. | |
def PI(prec) | |
raise ArgumentError, "Zero or negative argument for PI" if prec <= 0 | |
diff --git a/math.c b/math.c | |
index e3a78f7..e8b2525 100644 | |
--- a/math.c | |
+++ b/math.c | |
@@ -775,8 +775,10 @@ Init_Math(void) | |
#ifdef M_PI | |
rb_define_const(rb_mMath, "PI", DBL2NUM(M_PI)); | |
+ rb_define_const(rb_mMath, "TAU", DBL2NUM(M_PI*2.0)); | |
#else | |
rb_define_const(rb_mMath, "PI", DBL2NUM(atan(1.0)*4.0)); | |
+ rb_define_const(rb_mMath, "TAU", DBL2NUM(atan(1.0)*8.0)); | |
#endif | |
#ifdef M_E |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ git status -s | |
M ext/bigdecimal/lib/bigdecimal/math.rb | |
M math.c | |
$ /usr/local/bin/ruby --version # (after doing make && sudo make install) | |
ruby 1.9.3dev (2011-06-16 trunk 32123) [x86_64-darwin10.7.0] | |
$ /usr/local/bin/ruby -r bigdecimal/math -e 'puts Math::TAU, BigMath.TAU(100)' | |
6.283185307179586 | |
0.62831853071795864769252867665590057683943387987502116419498891846156328125724179972560696506842341359642961730265646057277261767213856E1 |
Here is tau.rb so you can just require 'tau'. (Maybe this should be a gem...)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# See http://tauday.com/ | |
module Math | |
TAU = PI * 2.0 | |
end | |
if defined? BigMath | |
module BigMath | |
module_function | |
def TAU(prec) | |
PI(prec) * BigDecimal("2") | |
end | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
$ ruby -I. -r bigdecimal/math -r tau -e 'puts Math::TAU, BigMath.TAU(100)' | |
6.283185307179586 | |
0.62831853071795864769252867665590057683943387987502116419498891846156328125724179972560696506842341359642961730265646057277261767213856E1 |
Update 1: I made this ticket which has been mostly ignored.
Update 2: Ticket has been noticed and discussed! :) Ticket has been categorised as joke! :(
Update 3: Some active debate is going on now and the ticket is now 'assigned'! :) See the details.
Update 4: (28-Jun-2014) Made a pull request in Github.
Update 5: See https://github.com/jneen/math-tau/
Thursday, March 17, 2011
beginning_of_fortnight gem is out
As promised I've cleaned up my beginning of fortnight hack and turned it into a proper ruby gem.
Install in the usual way:
It requires ActiveSupport and adds {next,end_of,beginning_of}_fortnight methods to the Date and Time class. They work the same as the *_week methods defined by ActiveSupport. You can set where you want fortnight boundaries to be (or just use the default).
For more info see:
I carefully made sure the docs look good in RDoc but, rubydoc.info uses YARD. So they don't look so great and actually the main usage examples which I put at the top of the file aren't showing at all...
I guess I will convert to using YARD. Is RDoc fading away? The website looks pretty musty.
(Just for fun, here are tweets where it all began).
Install in the usual way:
sudo gem install beginning_of_fortnight
It requires ActiveSupport and adds {next,end_of,beginning_of}_fortnight methods to the Date and Time class. They work the same as the *_week methods defined by ActiveSupport. You can set where you want fortnight boundaries to be (or just use the default).
For more info see:
I carefully made sure the docs look good in RDoc but, rubydoc.info uses YARD. So they don't look so great and actually the main usage examples which I put at the top of the file aren't showing at all...
I guess I will convert to using YARD. Is RDoc fading away? The website looks pretty musty.
(Just for fun, here are tweets where it all began).
Bash functions to dump and load a mysql database
Everyone probably has one of these, but here is mine. It's a bit rough but works for me.
If I was going to make it better I'd probably use getopt instead of $1 and $2 and then add options for changing the mysql user. (Currently it hard codes the user as root).
Put it in your .bash_aliases or .bashrc or wherever you keep these types of things.
Update: I made a set of rake tasks for doing this kind of thing, so I'm not actually using this any more.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Dump a mysql database to a gzipped sql file | |
dbdump() { | |
# (adjust defaults as required) | |
GZ_FILE=$1; [ ! -n "$GZ_FILE" ] && GZ_FILE="$HOME/.dbdump.gz" | |
DB_NAME=$2; [ ! -n "$DB_NAME" ] && DB_NAME='fms' | |
echo -n "Dumping database $DB_NAME to $GZ_FILE..." | |
# Add --extended-insert=FALSE to mysql command for more readable but MUCH slower sql | |
mysqldump -u root $DB_NAME | gzip - > "$GZ_FILE" | |
echo ' Done' | |
} | |
# Load a mysql database from a gzipped sql file | |
dbload() { | |
# (adjust defaults as required) | |
GZ_FILE=$1; [ ! -n "$GZ_FILE" ] && GZ_FILE="$HOME/.dbdump.gz" | |
DB_NAME=$2; [ ! -n "$DB_NAME" ] && DB_NAME='fms' | |
echo -n "Loading database $DB_NAME from $GZ_FILE..." | |
echo "DROP DATABASE $DB_NAME; CREATE DATABASE $DB_NAME;" | mysql -u root | |
zcat $GZ_FILE | mysql -u root -D $DB_NAME | |
echo ' Done' | |
} |
Thursday, February 24, 2011
Using the singleton class to include a module on-the-fly
I still don't entirely understand the syntax for accessing the singleton class, but I have found a use for it. :) The goal is to be able to make an object include a mixin on the fly.
If you do self.class.send(:include,module_name) instead of using the singleton class then the change affects every instance, not just the one you intended.
So it seems to work pretty well. Ruby is all like "sure buddy, have some rope, take as much as you need". :)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Where the magic happens... | |
module RuntimeInclude | |
def get_singleton | |
class << self | |
self | |
end | |
end | |
def runtime_include(the_module) | |
get_singleton.send(:include,the_module) | |
end | |
end | |
module Payments | |
module DPS | |
def foo | |
"dps" | |
end | |
end | |
module EWAY | |
def foo | |
"eway" | |
end | |
end | |
end | |
class Booking | |
include RuntimeInclude | |
def lets_go_eway | |
runtime_include(Payments::EWAY) | |
end | |
def lets_go_dps | |
runtime_include(Payments::DPS) | |
end | |
def foo | |
"none" | |
end | |
end | |
booking1 = Booking.new | |
puts "booking1 (original): #{booking1.foo}" | |
booking1.lets_go_eway | |
puts "booking1 (eway): #{booking1.foo}" | |
booking2 = Booking.new | |
booking2.lets_go_dps | |
puts "booking2 (dps): #{booking2.foo}" | |
puts "booking1 (still eway): #{booking1.foo}" | |
# You can flip it but only once. Scary..? | |
# I'm guessing once a module is included, re-including it does nothing | |
booking1.lets_go_dps | |
puts "booking1 (now dps): #{booking1.foo}" | |
booking1.lets_go_eway | |
puts "booking1 (is still dps): #{booking1.foo}" | |
# output: | |
# booking1 (original): none | |
# booking1 (eway): eway | |
# booking2 (dps): dps | |
# booking1 (still eway): eway | |
# booking1 (now dps): dps | |
# booking1 (is still dps): dps |
I should say that this technique was designed to be a quick fix to let us work around some legacy code that really should be refactored and fixed properly. I'm not saying this is a sensible design pattern, but it is cool that ruby can do it.
Here is a good explanation of singleton classes in ruby.
Friday, January 7, 2011
Some meta-progamming fun with Ruby (a define_method example)
I am currently working on my first gem which I hope to publish soon. It will be based on this beginning_of_fortnight method but will be more complete and flexible and (hopefully) it will be properly tested and documented. And it will be a gem of course, so it will be easy to install.
So the logic used to determine which half of a fortnight a given day falls in I wrote to work with Time objects. I decided that re-implementing it with Date objects would not be trivial. Take a look at this:
The result of subtracting two Dates surprised me a little. I guess Rational(7, 1) is 7 days. But anyway I didn't want to get any deeper into that so I did it like this:
So instead of figuring out how to apply my algorithm to Dates I will just convert them to Times, call the Time method on them, then convert them back to Dates afterwards.
Actually Date#to_time and Time#to_date are not part of the standard library but are defined by ActiveSupport. Since my gem requires ActiveSupport that's fine. Of course I could have written out the three methods but why not add some meta-programming coolness to the lazy to DRY it right up.
The splat on *args is important. My Time methods take an argument with a default value. The splatted args takes care of that so no matter how many arguments there are (or aren't), they will get passed correctly into the send. If anyone wants to check out (and/or checkout) the WIP gem, you can find it here (github). Feedback is welcome.
Todos include cleaning the rdoc output and adding gem dependencies to the gemspec (though I don't know if I'd want it to auto-install active support if you didn't have it already...)
So the logic used to determine which half of a fortnight a given day falls in I wrote to work with Time objects. I decided that re-implementing it with Date objects would not be trivial. Take a look at this:
>> (Date.today + 1.week) - Date.today => Rational(7, 1) >> (Time.now + 1.week) - Time.now => 604799.999613 >> (Time.now + 1.week) - Time.now => 604799.999532 >> 7.days.to_i => 604800
The result of subtracting two Dates surprised me a little. I guess Rational(7, 1) is 7 days. But anyway I didn't want to get any deeper into that so I did it like this:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Date | |
[:beginning_of_fortnight, :end_of_fortnight, :next_fortnight].each do |method| | |
define_method(method) do |*args| | |
self.to_time.send(method,*args).to_date | |
end | |
end | |
end |
So instead of figuring out how to apply my algorithm to Dates I will just convert them to Times, call the Time method on them, then convert them back to Dates afterwards.
Actually Date#to_time and Time#to_date are not part of the standard library but are defined by ActiveSupport. Since my gem requires ActiveSupport that's fine. Of course I could have written out the three methods but why not add some meta-programming coolness to the lazy to DRY it right up.
The splat on *args is important. My Time methods take an argument with a default value. The splatted args takes care of that so no matter how many arguments there are (or aren't), they will get passed correctly into the send. If anyone wants to check out (and/or checkout) the WIP gem, you can find it here (github). Feedback is welcome.
Todos include cleaning the rdoc output and adding gem dependencies to the gemspec (though I don't know if I'd want it to auto-install active support if you didn't have it already...)
Subscribe to:
Posts (Atom)