Skip to content

Instantly share code, notes, and snippets.

@erikaxel
Last active December 9, 2017 19:25
Show Gist options
  • Select an option

  • Save erikaxel/9f4cec27672bf3cbf4f6 to your computer and use it in GitHub Desktop.

Select an option

Save erikaxel/9f4cec27672bf3cbf4f6 to your computer and use it in GitHub Desktop.
Rails Engine with RSpec and Trailblazer

This example is called "stock". Use your own name instead.

  1. Setup new project: rails plugin new stock --mountable -T --dummy-path=spec/dummy
  2. Edit gemspec
  3. Edit engine.rb
  4. Install RSpec: bundle install rails generate rspec:install
  5. Make edits to spec/rails_helper.rb according to: http://blog.honeybadger.io/rails4-engine-controller-specs/
  6. Create your engine. See example model, concept and test
  7. Create migrations and run rake db:migrate
  8. Run rspec for tests or spec/dummy/bin/rails s for running test app
# lib/stock/engine.rb
require 'trailblazer'
require 'trailblazer/operation/model'
module Stock
class Engine < ::Rails::Engine
isolate_namespace Stock
def self.activate
Dir.glob(File.join(File.dirname(__FILE__), '../../app/concepts/**/*.rb')) do |c|
Rails.configuration.cache_classes ? require(c) : load(c)
end
end
config.to_prepare &method(:activate).to_proc
config.generators do |g|
g.test_framework :rspec
end
end
end
# app/models/stock/location.rb
module Stock
class Location < ActiveRecord::Base
end
end
# spec/models/stock/location_spec.rb
require 'rails_helper'
module Stock
RSpec.describe Location, type: :model do
it 'persists directly' do
location = Location.create!(name:'loc1')
expect(location.persisted?).to be_truthy
expect(location.name).to eq 'loc1'
end
it 'persists' do
location = Stock::Location::Create.(location: {name: 'loc1'}).model
expect(location.persisted?).to be_truthy
expect(location.name).to eq 'loc1'
end
end
end
# app/concepts/stock/location/operation.rb
module Stock
class Location < ActiveRecord::Base
class Create < Trailblazer::Operation
include Model
model Location, :create
contract do
property :name
validates :name, presence: true
end
def process(params)
validate(params[:location]) do |f|
f.save
end
end
end
end
end
$:.push File.expand_path("../lib", __FILE__)
# Maintain your gem's version:
require "stock/version"
# Describe your gem and declare its dependencies:
Gem::Specification.new do |s|
s.name = "stock"
s.version = Stock::VERSION
s.authors = ["TODO"]
s.email = ["TODO"]
s.homepage = "TODO"
s.summary = "TODO"
s.description = "TODO"
s.license = "MIT"
s.files = Dir["{app,config,db,lib}/**/*", "MIT-LICENSE", "Rakefile", "README.rdoc"]
s.add_dependency "rails"
s.add_development_dependency 'trailblazer'
s.add_development_dependency 'trailblazer-rails'
s.add_development_dependency "sqlite3"
s.add_development_dependency "rspec-rails"
end
@apotonick

Copy link
Copy Markdown

It looks as if the pivotal element is the Engine::activate method. If we provide that behaviour in trailblazer-rails and use trailblazer-loader instead of your manual requires, it should all be good.

@erikaxel

Copy link
Copy Markdown
Author

Not sure if that is enough, since Rails Engines don't automatically require the libraries if they are only specified in the gemspec. They are only required if they are present in the Engines gemfile. And if I put gem trailblazer-rails in the gemfile I get strange path errors.

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