Ruby – Time.next(:friday)
Thursday, March 31st, 2011This patch adds a method to find the next requested weekday.
This patch adds a method to find the next requested weekday.
I'm building a user model that keeps track of your parents and any children you should have. The acts_as_tree plugin
wouldn't have worked because it wouldn't allow for a parent to have many children. What's needed is a HABTM relationship. It's a quite simple relationship except for the :association_foreign_key option not being listed in the docs. Anyways I found some people discussing it here.
class User < ActiveRecord::Base has_and_belongs_to_many :parents, :class_name => "User", :join_table => "parents_children", :foreign_key => "child_id", :association_foreign_key => "parent_id" has_and_belongs_to_many :children, :class_name => "User", :join_table => "parents_children", :foreign_key => "parent_id" , :association_foreign_key => "child_id" end
describe User do
it "should have 0 children" do
User.new.should have(0).children
end
it "should have 0 parents" do
User.new.should have(0).parents
end
it "should have 1 child" do
parent = User.new
parent.children << User.new
parent.should have(1).children
end
it "should have 0 parents" do
child = User.new
child.parents << User.new
child.should have(1).parents
end
end
I found the stub_chain method very helpful when stubbing out objects for Rspec controller testing.
My index action is calling 2 named_scopes and then doing a find.
def index @exercise_logs = ExerciseLog.this_user(current_user).past.all end
When testing controllers your just trying to stub out a value for @exercise_logs not simulating an actual call to your model. So we'll use the stub_chain method to stub out our named_scopes like this.
it "assigns all exercise_logs as @exercise_logs" do
ExerciseLog.stub_chain(:this_user,:past).and_return([mock(ExerciseLog),mock(ExerciseLog)])
get :index
response.should be_success
end
It's important to filter out any sensitive data such as passwords from your log files. You can easily filter out data across your while application by calling filter_paramter_logging from your ApplicationController. In the example below I'm passing :password and :password_confirmation to remove their values from being placed in the logs.
class ApplicationController < ActionController::Base filter_parameter_logging :password, :password_confirmation end
You will now see "FILTERED" in place of sensitive data.
Parameters: {"x"=>"37", "y"=>"14", "action"=>"login", "authenticity_token"=>"JRFNcG9chNIpcsHoJzcQRRy1D6lIenjl7cWmvp3UpaI=", "controller"=>"videos", "user_id"=>"7-Jonathan-SpoonerJune", "video"=>{"password"=>"[FILTERED]", "email"=>"june@gmail.com"}}
Ruby implements Blocks, Procs and lambdas which are referred to as closures in the computer science community.
If you beginning to learn Ruby you will quickly run into code that looks like this.
a = ["dog", "cat", "bird"] a.alter_each! do |n, i| "#{i}_#{n}" end
So whats going on here?
We start off with an array of animal names and call the alter_each! method passing a block. In this block of code we can specify how we want to alter each item. Our example will prefix each animal name with it's position in the array. As the alter_each! method iterates through each item it will execute our block passing the value and index. Our block captures these params, prefixes the index to the name and returns the result.
Now lets look at the alter_each! method.
Notice the method doesn't specify any params, that's because a block is automatically assigned to yield keyword. yield is called like a function passing in the value and index of each item in the array and overriding the original value.
class Array def alter_each! self.each_with_index do |n, i| self[i] = yield(n,i) end end end
What if you need to pass a param to this method?
You can modify the method signature to accept params and finally catch the block with a param starting with an ampersand. In the example below our block will be captured with the &block param which we will invoke the call method. This is in place of using yield
class Array def modify_each!(add_one = true, &block) self.each_with_index do |n, i| j = (add_one) ? (i + 1) : i self[i] = block.call(n,j) end end end
Here is a full example that will prefix the index with the yield method and append the index with the call method.
class Array def alter_each! self.each_with_index do |n, i| self[i] = yield(n,i) end end def modify_each!(add_one = true, &block) self.each_with_index do |n, i| j = (add_one) ? (i + 1) : i self[i] = block.call(n,j) end end end a = ["dog", "cat", "cow"] a.alter_each! do |n, i| "#{i}_#{n}" end a.modify_each! false do |n,i| "#{n}_#{i}" end puts a
For blocks in the wild check out the ActiveRecord save method.
def save(perform_validation = true, &block) return false if perform_validation && block_given? && authenticate_with_sorenson? && !authenticate_with_sorenson result = super yield(result) if block_given? result end
References:
Understanding Ruby Blocks, Procs and lambdas