I have a module of custom examples, such as module ControllerHelperMethods module MyExampleGroupMethods def should_set_the_body_id(body_id) it "should set the body id to ''#{body_id}''" do assigns[:body_id].should == body_id end end end def self.included(receiver) receiver.extend MyExampleGroupMethods end end and in spec_helper: Spec::Runner.configure do |config| config.include(ControllerHelperMethods, :type => :controllers) end I have duplicate code in two of my custom examples, so I want to refactor it to a private method, but I can''t seem to get the private method to work. I have tried the most obvious way (private keyword followed by the method), and also a couple of more clever approaches that involved doing an instance_eval in self.included. First, should I be able to call private methods in my custom examples? If so, how. Peace. Phillip
On Thu, Dec 31, 2009 at 12:54 PM, Phillip Koebbe <phillipkoebbe at gmail.com>wrote:> I have a module of custom examples, such as > > module ControllerHelperMethods > module MyExampleGroupMethods > def should_set_the_body_id(body_id) > it "should set the body id to ''#{body_id}''" do > assigns[:body_id].should == body_id > end > end > end > > def self.included(receiver) > receiver.extend MyExampleGroupMethods > end > end > > and in spec_helper: > > Spec::Runner.configure do |config| > config.include(ControllerHelperMethods, :type => :controllers) > end >First of all, you can simplify this by using extend() instead of include() on the config object: module ControllerMacros def should_set_the_body_id(body_id) it "should set the body id to ''#{body_id}''" do assigns[:body_id].should == body_id end end end Spec::Runner.configure do |config| config.extend(ControllerMacros, :type => :controllers) end Note that we generally referred to as "macros," so I recommend using that name for consistency.> I have duplicate code in two of my custom examples, so I want to > refactor it to a private method, but I can''t seem to get the private > method to work. I have tried the most obvious way (private keyword > followed by the method), and also a couple of more clever approaches > that involved doing an instance_eval in self.included. >I *think* that if you use extend instead of include + included hook, you can just use the private keyword and all will be well. HTH, David> First, should I be able to call private methods in my custom examples? > If so, how. > > Peace. > Phillip >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20091231/ae6afd61/attachment-0001.html>
Hi David, First, thanks for the suggestion. I like that better. Second, my motivation for doing this was born out of not being able to do something I wanted to do in Remarkable. However, as I was trying to explain what it was I wanted to do, I just discovered how to do it in Remarkable. So, the immediate need for knowing how to call a private method is no longer valid, but I would like to go ahead and explain what I was trying to do to see if it is actually possible. I still have custom macros that I might need to refactor at some point. Here is the relevant code example: http://gist.github.com/266873 [By the way, I didn''t intend for the gist to be formatted quite like that. I am fond of 4 character tabs, but I realize that most people in the ruby community use 2 spaces, so I copied the code to a new textmate window, reformatted it, then copied and pasted into the gist. But it still come out like that, so I don''t know what I''m supposed to do.] I was attempting to create my own should_set_session so I could use values from instance variables. I didn''t see how to do that in Remarkable until just a few minutes ago. It can be accomplished by using :to => proc { @user.id }. I was experimenting with where to call get_value_from_options from. When I try inside the "it", I get the NoMethodError. When I call it from outside of the it, get_value_from_options gets called, but then I don''t get the instance variable like I expect. I believe I understand why that is, though. The instance var is created in the before, which is more or less an it, so it has the same scope. So when called from outside of the it, there is no instance var @user. So my question now is simply: Can I even do what I want to do? Thanks, Phillip
On Thu, Dec 31, 2009 at 2:05 PM, Phillip Koebbe <phillipkoebbe at gmail.com>wrote:> Hi David, > > First, thanks for the suggestion. I like that better. > > Second, my motivation for doing this was born out of not being able to > do something I wanted to do in Remarkable. However, as I was trying to > explain what it was I wanted to do, I just discovered how to do it in > Remarkable. So, the immediate need for knowing how to call a private > method is no longer valid, but I would like to go ahead and explain > what I was trying to do to see if it is actually possible. I still > have custom macros that I might need to refactor at some point. > > Here is the relevant code example: > > http://gist.github.com/266873Ok - now I understand the problem :) You''ll see that even if you make the method public, it still won''t work. Here''s why: By default, the describe() method returns a class which is a subclass of ExampleGroup. Any methods defined in the describe() block become class methods on that subclass of ExampleGroup. The module is extending the ExampleGroup class, so should_set_session and get_value_from_options are both class methods. The it() method (sort of) returns an _instance_ of the same class. It can only access instance methods directly, _but_ because it is an instance of the class that was extended with the module, you can access get_value_from_options like this: ... it "should set session[:#{key}]" do value = self.class. get_value_from_options(options) ... Make sense? Cheers, David [By the way, I didn''t intend for the gist to be formatted quite like> that. I am fond of 4 character tabs, but I realize that most people in > the ruby community use 2 spaces, so I copied the code to a new > textmate window, reformatted it, then copied and pasted into the gist. > But it still come out like that, so I don''t know what I''m supposed to > do.] > > I was attempting to create my own should_set_session so I could use > values from instance variables. I didn''t see how to do that in > Remarkable until just a few minutes ago. It can be accomplished by > using :to => proc { @user.id }. > > I was experimenting with where to call get_value_from_options from. > When I try inside the "it", I get the NoMethodError. When I call it > from outside of the it, get_value_from_options gets called, but then I > don''t get the instance variable like I expect. I believe I understand > why that is, though. The instance var is created in the before, which > is more or less an it, so it has the same scope. So when called from > outside of the it, there is no instance var @user. > > So my question now is simply: Can I even do what I want to do? > > Thanks, > Phillip >-------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20091231/b4f69847/attachment.html>