Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Edits to keep code DRY #111

Merged
merged 1 commit into from
Apr 26, 2014
Merged

Edits to keep code DRY #111

merged 1 commit into from
Apr 26, 2014

Conversation

JCook21
Copy link
Collaborator

@JCook21 JCook21 commented Apr 20, 2014

  • Overrode say_status and system methods to put checks for options[:quiet] and options[:pretend] in one place.
  • Edits to make sure that shell.say_status is not called since this does not invoke the overridden say_status method. Edits to tests as a result of this too.
  • Removed all uses of 'unless options[:pretend]' and 'unless options[:quiet]' since this is now handled in the overridden methods.

@@ -2,6 +2,14 @@
class Homesick
# Various utility methods that are used by Homesick
module Utils
def say_status(*args)
super unless options[:quiet]
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this try to extract options out of *args too? That would allow one-off programmatically quiet command, versus globally with --quiet. Same idea applies to system below.

@technicalpickles
Copy link
Owner

Definitely cleans things up nicely 👍

@JCook21
Copy link
Collaborator Author

JCook21 commented Apr 20, 2014

@technicalpickles I've added some code to allow a final boolean argument to be passed to both say_status and system. I'm not sure if there's a better way to implement this than I've done though. I'd appreciate any comments.

def system(*args)
pretend = %w(TrueClass FalseClass).include?(args.last.class) ? args.pop : false
super(*args) unless options[:pretend] || pretend
end
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking that say_status and the system methods could be refactored a tiny bit like this:

def boolean? object # it might be best to make this method private or protected
  object == true || object == false
end

def say_status(*args)
  quiet = args.count == 4 && boolean?(args.last) && args.pop
  super(*args) unless options[:quiet] || quiet
end

def system(*args)
  pretend = boolean?(args.last) && args.pop
  super(*args) unless options[:pretend] || pretend
end

Also, it would probably help to add some brief documentation comments for these methods either way. What do you think?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nicolasmccurdy I like that, it's neater than what I came up with. I'll add a commit with that.

@nickserv
Copy link
Collaborator

Looks good. 👍

@nickserv
Copy link
Collaborator

I just realized that due to #74 (and especially #101, which has already been merged), multiple methods would be used to avoid shell calls instead of simply calling system. As a result, it would be trickier to keep things DRY by overriding these methods while still migrating away from shell calls.

I'm thinking about these options:

  1. Use some metaprogramming magic to automatically wrap methods like system, FileUtils.*, and say_status in stub commands that only perform the appropriate action if the current command line options and overridden options (if any) allow it.
  2. Provide helper methods like pretend? and quiet? that look at command line and other options for you and return a boolean. This would be somewhat similar to how things worked before this pull request.
  3. Require that code like unless options[:quiet] be used manually for methods besides system and say_status. This might be the simplest option, since different people may write multiple new methods that need to all use quiet and/or pretend options.

@JCook21
Copy link
Collaborator Author

JCook21 commented Apr 21, 2014

@technicalpickles @nicolasmccurdy I've just had another stab at this, using meta-programming to dynamically define methods that should be 'pretendable' or 'quietable'. A couple of points about this:

  • I'm not totally sure that this will work as written. In the block that used to define the method I have to access the number of parameters that the super method accepts through method(method_name).parameters.count. Do either of you know if this will work as intended?
  • This will only work as written for methods within the context of the Homesick class. Do either of you have any ideas as to how this could be updated to support methods from other classes (such as FileUtils)? I was thinking of using a hash of classname => method_name. Do you think that would be possible?

@JCook21
Copy link
Collaborator Author

JCook21 commented Apr 21, 2014

I've just realised that method(method_name).parameters.count doesn't seem to work. What I was trying to find are cases where methods have an extra argument and the final argument is a boolean. This falls down on methods like system though as it takes a variable number of arguments... Does anyone have any ideas on how to achieve this cleanly?

@JCook21
Copy link
Collaborator Author

JCook21 commented Apr 21, 2014

This really isn't working as intended. The way I'm trying to pass a boolean value as the last argument to allow the 'quietable' or 'pretendable' behavior is not working at all. I'll take another look at what we need to achieve and how I'm trying to do it and will reopen this PR then.

@JCook21 JCook21 closed this Apr 21, 2014
@JCook21 JCook21 reopened this Apr 22, 2014
@JCook21
Copy link
Collaborator Author

JCook21 commented Apr 22, 2014

I've given this some more thought have decided to reopen this. The approach I was trying was to try to detect if a final boolean argument was being passed and to use that to set the pretendable or quietable behaviour. I don't think this is going to work due to the fact that many methods can have an indeterminate number of arguments (e.g. system). I think it may be better to keep this simple and just look in the options to see if the pretendable or quietable behaviour should be invoked. This could also be done programmatically by manually setting the option before calling the method that's being overridden, giving us the behaviour that @technicalpickles suggested. Let me know if you can think of a better way to achieve this.

@nickserv
Copy link
Collaborator

👍 Looks good to me.

By the way, you might want to merge/rebase on master now that #110 is merged.

@JCook21
Copy link
Collaborator Author

JCook21 commented Apr 22, 2014

I just rebased on master and I think I've fixed the issues that came about as a result of this. @nicolasmccurdy could you have another look now?

options, skipping their default behaviour if so.
@JCook21
Copy link
Collaborator Author

JCook21 commented Apr 26, 2014

Any more comments on this or should I go ahead and merge it?

@nickserv
Copy link
Collaborator

:shipit: Merge it!

JCook21 pushed a commit that referenced this pull request Apr 26, 2014
@JCook21 JCook21 merged commit 1a44edc into technicalpickles:master Apr 26, 2014
@JCook21 JCook21 deleted the Pretend branch April 26, 2014 21:45
@JCook21
Copy link
Collaborator Author

JCook21 commented Apr 26, 2014

Merged!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants