GithubHelp home page GithubHelp logo

Explore ways to reload gems about rails HOT 8 OPEN

fxn avatar fxn commented on June 26, 2024
Explore ways to reload gems

from rails.

Comments (8)

rafaelfranca avatar rafaelfranca commented on June 26, 2024 1

That is the contract that Rails expects. If a library needs to integrate well with Rails and its reloaders it needs to include a Engine. I don't think we should change that contract.

from rails.

davidmilo avatar davidmilo commented on June 26, 2024 1

I am a huge fan of extracting code from rails apps into gems. With larger codebases there are many things which can be extracted and either shipped as a.) public gem for everyone to use or b.) private gem which can be used in other product you are using within the company. I think that moving logic to gems helps you modularise large rails app better. It makes it easier to re-use lot of code across different products.

These gems are, in many cases, not related to rails at all. They either extract some piece of business domain specific to the company or product you are working on. Sometimes they can be some nice algorithm solving general problem. Some examples could:

  • gem which knows how to talk to some API service we are using which maybe doesn't have ruby client.
  • gem which knows how to talk to some internal service we are using in the company - for example wrapper on how to talk to our specific instance of Solr/Elastic search/
  • gem made to crawl specific websites (I worked at a place which was crawling 50 public websites for different sources of information) - organising these different crawlers into smaller gems which know how to handle specific sources can be quite useful.
  • gem to wrap up our home made XML diffing algorithm
  • gem which wraps our internal design system

Why should these be Rails engines? They have nothing in common with Rails - they are not additions or any extensions of Rails. They do not add any features to the framework. They are just pure ruby classes doing something which can be used anywhere. Why should I make them dependant on Rails?

I could think about 3 different cases when extracting into gems would come handy:

Example 1

  • We have a huge product which is the main product of company A. Company wants to make some new products where lot of logic/tooling could be shared.
  • My first step would to make local gems along side my main product. This might take some time because code extraction can sometimes be difficult. You need to find abstraction of the problem. It can be sometimes tricky to extract logic from Rails if code was not made with good separation of concerns and when code is too bound to the framework.
my_repo/
  my_rails_app/
  my_gem_1/
  my_gem_2/
  my_gem_3/
  • Main product is the main consumer of these gems. Majority of changes and features are developed along side the development of the product. We can easily modify code of the gems and code of the product at the same time. These gems can be published to a private company repository as needed when it is meaningful to do a new version release.
  • We can eventually start making new products which can start re-using these gems to re-use lot of code which would be similar across the products.

Example 2
Mono repos are getting extremely popular! They come with lot of benefits. It would be very common to run in a setup where you have 3-4 products and 5-7 gems in a same repo

my_mono_repo/
  my_product_1/ # rails app
  my_product_2/ # rails app
  my_product_3/ # rails app
  my_gem_1/
  my_gem_2/
  my_gem_3/
  my_gem_4/
  my_gem_5/

Working across 8 different github repos can create lot of maintenance, manual work, headache and lot of wasted time. Mono repos come with their own problems, but benefits of being able to change some shared code and directly update products using it at the same time can provide huge boosts to development process. Imagine opposite process:
Updating gem in a github repo. Releasing the gem. Then update 3 other repos which are using the gem and release/redeploy them separately. Lot of these things can be easily simplified by mono repo structure and good CI setup.

What does Rails framework want to do about this new boom of mono repos? Should there be some support for it to make it easier to work on several different Rails products and share code in between?

Example 3

  • I am making a framework which crawls lot of different public authority websites and collects different legal information/regulations etc into a single place.
  • My Rails all is the framework itself which runs different crawlers.
  • To keep code nicely separated, it is good idea to make each crawler its own gem. Small gem which knows how to crawl single website and returns what was found in some generalised format. Each gem is easy to re-use, test and develop on it's own. Good separation of concerns - gems doesn't need to know about rest of the Rails app or other crawlers.
  • In this case gems will probably never be used by other products but process of extracting code into small gems helps keep codebase more clean and understandable.
  • Gems helps you to more clearly define dependencies and creates more natural modules.

from rails.

rafaelfranca avatar rafaelfranca commented on June 26, 2024

Any reason why this doesn't work today? We have many gems in our application (70+) and they are all reloaded. They just need to be Rails engines and inside the application directory.

from rails.

fxn avatar fxn commented on June 26, 2024

@rafaelfranca I suggested this, but @davidmilo does not seem to want its gem to be an engine.

@davidmilo to help discuss, could you please be more explicit about your use case?

from rails.

davidmilo avatar davidmilo commented on June 26, 2024

Maybe I am not understanding the contract you are talking about well. I guess your idea would be that everything which wants to be used in Rails should ship with rails engine? Am I understanding it correctly? I think it is little weird to require that of gems and libraries which does not directly interact or depends on Rails. I think separation that:

  • gems which adds direct logic/features to the framework, are Rails engines
  • gems which are just pure ruby classes which can be used any other framework or just other pure ruby code, should NOT be Rails engines.

from rails.

rafaelfranca avatar rafaelfranca commented on June 26, 2024

Why should these be Rails engines?

Because you want them to be reloaded in a Rails application. Engines aren't for telling a gem has to do with Rails. It is to teach Rails applications what to do with those gems.

The gems don't become Rails engines, they include Rails engines. For this gem to be used by other frameworks it doesn't need to load the Rails Engine.

So by including a Rails::Engine subclass in your gem your not making your gem a Rails engine, you are including an optional glue to to your gem for it to be able to be properly glued to a Rails application.

Note that I'm telling you to do rails plugin new my_gem, I'm only telling you to include a subclass of Rails::Engine. Like many gems, that can and are used outside Rails app do.

https://github.com/drapergem/draper/blob/26a18c8cc9ce112f7cf2a308b52952680d9a2cdf/lib/draper.rb#L32
https://github.com/instacart/makara/blob/9e7960558a75aed3f97ba4cbab61abb64687ec3c/lib/makara.rb#L3
https://github.com/thoughtbot/bourbon/blob/71d4776757bbd0d7da47b5660eb6d1f3bf73fc3f/lib/bourbon.rb#L5
https://github.com/carrierwaveuploader/carrierwave/blob/ed8799191824a4d2762eb1028c01220102699377/lib/carrierwave.rb#L51
https://github.com/collectiveidea/delayed_job/blob/b66bb64437a8606a414a390531ac73108911434e/lib/delayed/railtie.rb#L5
https://github.com/primer/octicons/blob/6bc78de32be1a218a69e10a731072331ba94e7f9/lib/octicons_helper/lib/octicons_helper.rb#L3

from rails.

fxn avatar fxn commented on June 26, 2024

I believe that approach is not quite right for this use case.

The gem needs its own autoloader, because when it ships it needs to autoload its code by itself. And the gem has no initializer to run or any integration to be done with Rails projects.

Also, when the gem ships, Rails projects using the gem should not reload the gem.

Point is, it would be convenient to reload the gem's loader while the gem is being developed and used via a Rails application.

This does not necessarily mean we have to do anything in Rails, eh? This ticket only wants to trigger a discussion.

I have a busy week and have not been able to sit down and think about this, but my main ideas to be explored are:

  • The gem should expose its loader instance.
  • The gem should expose its project tree.
  • The Rails application should be configured to watch the gem's project tree.
  • If the gem's source code changes, when the time arrives in Rails's lifecycle, the gem's loader would be reloaded first, and then the main loader would be reloaded. This order is important.

If something like that works with existing APIs, we do not need to do anything, the outcome of the discussion would be what to put in David's app initializers to make this happen.

from rails.

rails-bot avatar rails-bot commented on June 26, 2024

This issue has been automatically marked as stale because it has not been commented on for at least three months.
The resources of the Rails team are limited, and so we are asking for your help.
If you can still reproduce this error on the 7-2-stable branch or on main, please reply with all of the information you have about it in order to keep the issue open.
Thank you for all your contributions.

from rails.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.