0

Suppose I have a few classes defined in a nested module stracture:

Core::UI::Components::TextView
Core::UI::Components::ImageView
Core::UI::Components::Checkbox

Now I have a class that wanna use this classes suppose this class is not inside the 'Core' Module.

class XView
  def render
    Core::UI::Components::ImageView.new('x').render
    Core::UI::Components::TextView.new('x').render
  end
end

I want to avoid all the module names writing so I refactor this to

class XView
  def render
    ui = Core::UI::Components
    ui::ImageView.new('x').render
    ui::TextView.new('x').render
  end
end

Is there a ruby standard for static import of module/class ? how would this be written in the ruby way?

thanks,

0

2 Answers 2

2

I don't think there's any import construct in Ruby to do this.

If you will only need this in your render method, then I agree with your approach. If you may need it elsewhere, then you could define a constant in your class to alias the longer compound name, such as:

class Foo
...
COMPONENTS = Core::UI::Components
...
def render
  COMPONENTS::ImageView...
  ...
end

Alternatively, you could alias each class:

IMAGE_VIEW = Core::UI::Components::ImageView
...

I defined these constants in all upper case as a cue to the reader that these are not classes in your current module, but you could also use camel case.

Sign up to request clarification or add additional context in comments.

2 Comments

Wouldn't this still need to be COMPONENTS::ImageView because ImageView is not a method.
@engineersmnky Yes, you're right, thanks. I've corrected it, and also edited to use the term 'alias' to clarify my intent.
1

If Core::UI::Components is just for namespacing and does not include any method declarations then. You can provide access to these classes via Module#include which is specifically designed for "mix-ins" e.g.

class XView
  include Core::UI::Components
  def render
    ImageView.new('x').render
    TextView.new('x').render
  end
end

Since ImageView and TextView are classes inside the module Core::UI::Components including this module in XView will allow for direct access to these classes by "including" them in the current namespace which appears to be what you are looking for. Obviously this could be done at any level e.g.

class XView
  include Core::UI
  def render
    Components::ImageView.new('x').render
    Components::TextView.new('x').render
  end
end

would also work if you needed access to other modules or classes contained in the Core::UI namespace.

Otherwise you could create a first class DSL for this such as

module Core
  module DSL
    def text_view(*args)  
      UI::Components::TextView.new(*args)
    end 
    def image_view(*args)
      UI::Components::ImageView.new(*args)
    end
  end
  extend DSL
end

Then the XView would look like

class XView
  def render
    Core.image_view('x').render
    Core.text_view('x').render
  end
end

10 Comments

This approach accomplishes the naming convenience, but does much more; it modifies the includeing class. If the poster's intention was to merely make the name more easily available (as is the case with Java imports), then this is overkill and may be undesired. Personally, my optimum point is creating a short constant alias and using that; even if it's cryptic (e.g. CUC), its scope is small and is easily looked up.
@KeithBennett to each their own as I feel personally your implementation is far less idiomatic. if the goal is just to shorten the namespacing then just a top level UIComps= Core::UI::Components would do your better yet first class DSL inside Core like def self.text_view(*args); UI::Components::TextView.new(*args); end; then the OP could just call Core.text_view('x') which is not uncommon
@KeithBennett updated with a DSL implementation by the way "cryptic" is not generally the ruby way. Ruby is designed around the idea of making code readable without the need for introspection. Also include does not technically "modify" the class but rather injects the included module into the inheritance stack just above the including class.
Modifying the inheritance chain seems like a bad idea since the asker said he just wants to "avoid all the module names". If Core::UI::Components defines any methods, include could have surprising side-effects.
@Max that is how include works is by modifying the inheritance chain but I agree with the second part but that is implementation specific and no information was provided for such.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.