Skip to content

Instantly share code, notes, and snippets.

@fernandes
Last active June 19, 2020 16:22
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save fernandes/cee84403e6f317fad6d3 to your computer and use it in GitHub Desktop.
Save fernandes/cee84403e6f317fad6d3 to your computer and use it in GitHub Desktop.
COBRA - Component-Based Rails Applications

Component-Based Rails Applications (#cobra)

What is it?

Cobra is a way to organize your rails application, imagine it like a new way for packaging your rails apps

These are my annotations based on work of @shageman and @benjaminleesmith from Pivotal

Baby steps

So lets start write some code!

bundle exec rails plugin new shopping --full --mountable -d sqlite3 --skip-test-unit --dummy-path=spec/dummy -B
cd shopping
bundle install

What are the first steps before go coding?

  • Edit your gemspec
  • Monkeypatch migrations
  • Load component dependency automatically

Editing your gemspec

No secrets here, fill in the field (don't forget to remove the TODO:)

Monkeypatch migrations

Here is a nice trick (okay, its a monkey patch, but really helps you save a lot of time), instead of install migrations of your engines and make your migrates / rollbacks, in production this can be useful, but during development is a PITA

So we monkey patch our engine so when the wrapper application runs rake db:migrate our engine's migrations are run too.

So, lets do it, in your lib/shopping/engine.rb, you go from this:

module Shopping
  class Engine < ::Rails::Engine
    isolate_namespace Shopping
  end
end

to this:

module Shopping
  class Engine < ::Rails::Engine
    isolate_namespace Shopping
    
    initializer :append_migrations do |app|
      unless app.root.to_s.match root.to_s
        config.paths["db/migrate"].expanded.each do |expanded_path|
          app.config.paths["db/migrate"] << expanded_path
        end
      end
    end
  end
end

easy hun, now you only need to rake db:migrate and db:rollback

Load component dependency automatically

You added a gem on your component.gemspec, runned bundle install and what, it raised an error on wrapper it was not found?!

Its because bundle just requires dependencies, in a non recursive way, so you need to load it.

Go to lib/component/engine.rb and add:

module Component
  class Engine < ::Rails::Engine
    initializer "require stuff" do
      require "add_gem"
    end
  end
end

Damm, everytime we add a new dependency we need to do this? And if we remove a gem, it will raise an error when we try to require it? How we do automatically?

Go to lib/component/engine.rb and instead of add the single dependency, add this:

module Component
  class Engine < ::Rails::Engine
    
    # Initialize engine dependencies on wrapper application
    Gem.loaded_specs["component_template"].dependencies.each do |d|
      begin
        require d.name
      rescue LoadError => le
        # Put exceptions here.
        raise le if d.name !~ /factory_girl_rails/
      end
    end
  end
end

Template

Hey, make this all the time, can be not so cool, #cobra is about development pleasure

Check out my wrapper template, theres a copy_template.sh to make your #cobra coding easier!

@RaVbaker
Copy link

Could you @fernandes provide a correct link to wrapper template you mention in this README?

@fernandes
Copy link
Author

I removed the template 😢

I pushed it again https://github.com/fernandes/cobra_template

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