Is it possible to create whole rails applications under a common namespace?
Lets assume that my company name is Acme, Inc. and I have the following rails projects: Blog, Store, WebService.
By default, if I do something like rails new blog the generated applications will be like:
module Blog
class Application < Rails::Application
module Store
class Application < Rails::Application
module WebService
class Application < Rails::Application
where every project/application is self contained and there is no implicit reference to the company. Ideally I would like to have all this applications under the company namespace, so we can refer to them as:
AcmeInc::Blog::Application
AcmeInc::Blog::Entities::Article
AcmeInc::Store::Application
AcmeInc::Store::Entities::Product
AcmeInc::Store::Entities::Order
AcmeInc::Store::Entities::Customer
etc...
Is this possible? Recommended?
Using:
ruby-2.0.0-p451, rails 3.2.17
Update
Snapshot of generated files and project structure after doing rails new acme/blog as suggested:
The correct way to do this is with engines. Each engine is like a standalone app, with it's own routes, test suite, etc, but you can have some common infrastructure like rake tasks, etc.
http://guides.rubyonrails.org/engines.html
I think I am probably late here to answer this, as others have already suggested nice approaches. Like, maintaining code within one common repository and creating rails engine.
I would like to share this famous project called spree, which follows the architecture you're looking for. You can visit spree's code on github here.
For example:
Spree::Core - spree_core engine as a gem to maintain all models and base modules etc.
Spree::Backend - spree_backend engine as a gem to maintain all admin related controllers, views, assets etc.
Spree::Frontend - spree_frontend engine as a gem to maintain user facing code i.e. controllers, views, assets related to it.
I guess you can use it as a reference for your application development.
If your trying to manage your code, why don't you just make a Blog Gem that you can include in each application. Then you would manage the code under one common repository for the Gem. Sees to me that's the Rails/Ruby way to do this
Related
I have been using Rails Admin in my Rails application for a while now. Recently, we decided to separate our API from our Web Application and we decided to have our models (that are shared between the two) in a Gem.
Now, Rails Admin, which somehow scans the models in my app, have stopped showing me these models in the admin panel (even though they are accessible from the application).
Any idea on how to fix it?
My gem directory structure is:
name1-name2(main directory)
lib(directory)
name1(directory)
name2(directory)
mymodel.rb
name2.rb (which requires all other models)
gemspec
Use config.included_models which whitelists models, both healthier and will let you include gem models:
config.included_models = ['User', 'YourNameSpace::ModelName']
Try making a local version of the model that inherits from the shared version in the gem. Rails admin might be looking only at models local to your app.
I want to create a sms payment engine and reuse it in several applications. It would be best to be able to just copy/paste one directory, maybe configure some minor stuff and just have it working (with views, controllers, etc.).
What's the best way to do this? Of course I'm not asking about this sms thing but about the way to create an isolated piece of application. It's something like a helper application inside of the major application.
There a three ways to build Rails extensions : plain-old ruby code, Railties and Engines.
Railties and Engines allow you to interact with the Rails framework during the initialization using hooks and therefore extend Rails. Actually, every major Rails component (ActiveRecord, ActionPack, etc.) is a Railtie.
The main difference between a railtie and a Rails engine is that an engine can define its own configuration, models, controllers and views. In a way, an engine is a Rails application you can deploy in another one. In your case, I guess a Rails Engine would be the right choice.
Whatever the option you use, you will have to build a gem to distribute your extension and share it across projects.
Here is a gist explaining both the Railtie and Engine concepts
A guide to starting your own rails engine.
Enginex, a command line tool which creates a Rails 3 Engine
I guess the best way to reuse your code is putting them to a gem, then install that gem.
I think the best way to extract reusable part of your application is to create a RubyGem. You can find a tutorial about creating RubyGems here. And there is a Jeweler, a very nice tool to create RubyGems. More about Jeweler, you can find here
currently I am working on a RoR application (2.3.14 with ActiveRecord) (let's call it A).
Now I started another project B (a remote testing app using capybara, looks something like this: https://github.com/searls/remote-capybara-cucumber-example).
But now I need to have access to the model of application B for test data setup (and possibly test assertions). I therefore would like to use the existing model classes (and some additional libraries like factory_girl if necessary).
I certainly don't want to wrap my project B in a Rails app and copy the model classes. So is there a way to organize A so that B can access the model and create/update/destroy entities?
Are there any keywords for further research (I tried several google searches containing rails model as a gem, as a plugin, externalize rails model etc... but nothing useful turned up (mostly the documentation of ActiveRecord)
Rails 2.x does make it very hard to share the model layer between two applications.
If you don't care about maintaining migrations twice, you can put the models into a gem and then require it in your apps.
Another way is to symlink the db and app/models directories from both applications to a shared folder. This works quite well though you have to be careful because rake tasks and generators now affect both applications.
Rails 3.1 ships with an improved implementation of rails engines. Engines allow you to isolate parts of an rails application and package them up as a gem.
You could try using an alias (symbolic link) to the A's app/models directory in the B project.
On Mac/Linux:
ln -s /volumes/code/project-a/app/models/ /volumes/code/project-b/models
I have a number of engines which are also gems and also applications (Rails3). They are gems so they can be easily installed and the dependencies managed via bundler in more than one application (its a whole stack upon which multiple applications are built). They are engines to take advantage of Rails resources - models and such. They are applications for two reasons: 1) to provide a full testing environment which is isolated from their including applications so you can do 'rails c' for example and 2) in order to run things like 'rake db:migrate' and seed and more.
I want both my engine and my application to inject some mixins into lower level dependencies. Here is the solution I came up with. It works fine - I am just wondering if anyone has any criticisms of the approach OR a best practice to share regarding the sharing issue OR the overall idea of engine-gem-applications:
The engine:
#my_engine/lib/my_engine.rb
require 'my_engine/config.rb'
module MyEngine
class Engine < Rails::Engine
config.to_prepare do
MyEngine.inject_mixins
end
end
end
The application:
#my_engine/config/application.rb
require 'my_engine/config'
module MyEngine
class Application < Rails::Application
config.to_prepare do
MyEngine.inject_mixins
end
end
end
The mixin:
#my_engine/lib/my_engine/config.rb
module MyEngine
module CLASSMETHODS
def inject_mixins
::ApplicationHelper.send(:include, MyEngine)
::SomeDependency::SomeClass.send(:include, MyEngine::SomeClassMixin)
end
#root should be defined as the root of this engine, ie relative to this file
def root
File.join(File.dirname(__FILE__), '..','..')
end
end
extend CLASS_METHODS
end
(Update: I edited the above to wrap the module in my_engine module, otherwise more than one engine using this pattern simultaneously could have unpredictable effects, like MyEngine.root == SomeOtherEngine.root)
There's no rhyme or rule to this, but you have a couple different options.
Your gem's tests can contain a dummy application for testing. Devise does this, for example. This is accepted practice for gems that are heavily Rails-dependent.
You can also keep it separate. In the past I've set up a testing application with a Gemfile that points to the gem via path (gem 'mygem', :path => 'some/path'), which makes testing relatively easy. This can double as a sample application that you can provide in a separate repository (keep in mind when tagging the gem you should change the sample application's :path parameter to a specific version). The benefit here is that your sample application is always kept up to date.
If you're simply talking about unit testing models, you can skip the above and just add a testing dependency on Active Record and SQLite. Keep fixture data with the gem.
Since you have several of these engines and they will be mixed and matched in different applications, my suggestion is to set up an application that uses all of these gems and serves as your functional testbed. Keep unit tests with the individual gems, of course. This has the added benefit of integration testing between all engines, to ensure there are no conflicts.
With a Ruby module, you can cluster together a bunch of methods that you might use in one place and then include them into a class so it's as if you had written them in that class.
What kinds of practical uses are there for Ruby modules in a rails app?
I would appreciate if someone could mention an example of where they've actually used a module of their own so I have a sense of what situations I should be thinking about creating them. Thanks.
1) Any time I'm about to duplicate (or substantially duplicate) a piece of code: "oh, i could just cut/paste into this other controller . . . "
2) Any time I write code that is very obviously going to be reused in the future.
3) Code of substantial size that has a specific purpose, where that purpose is fairly distinct from the main purpose of the controller/model. This is somewhat related to (2), but sometimes code won't get reused but a module helps for organization.
You can place them in the /lib directory and they'll be loaded with your Rails project.
For example, you can view this repo of mine of an old project: lib directory of a Rails project
So for example, I have the following module:
google_charts.rb
Module GCharts
class GoogleCharts
def some_method
end
end
end
And anywhere in my Rails app, I can access the methods.
So if I were to access it from a controller, I would simply do:
require 'google_charts'
GCharts::GoogleCharts.some_method
We use modules for functionality that isn't tied to ActiveRecord models and hasn't been abstracted into a plugin or gem.
A recent example from our production code base is a library for integrating with Campaign Monitor for email list management. The core of the system uses our user model, but the actual interaction with the extenrl service is abstracted through a module that lives in /lib.