maximus ツ
maximus ツ

Reputation: 8065

Using rails inside gem as a dependency

While browsing through the active-admin code, I found that Gemfile contains the rails entry.

rails_version = detect_rails_version
gem 'rails', rails_version

Does that mean active-admin internally creates a rails server which is not the main rails app?

If Yes, will that lead to performance issues and using it with complex rails applications is a bad practice?

if No, what is the use of it in active-admin Gemfile?

Googled a lot with different keywords which only leads to gem install and related results.

I would be glad if somebody put some insights. Thanks :)

update1: After Gaurish answer and googling, it seems that Gemfile inside gem is used to list dependencies needed for gem internally. But it create another question, what happens when application gems and gems' gem conflits?

update2: Can we use active-admin standalone, since it has rails as a dependency? (Just installing active-admin by gem install active-admin instead of keeping it in some other rails application.)

Upvotes: 0

Views: 239

Answers (1)

CuriousMind
CuriousMind

Reputation: 34155

No. This seems a bundler issue. this code just declares a dependency on rails. sound's strange? Here is what I think is happening.

the usual way is to declare your dependencies in .gemspec file by using following line:

s.add_dependency("rails", ">= 3.0.0")

the above lines add a dependancy on rails v3.0 & above(v3.1,v3.2). now this works fine for other gems & bundler will auto resolve dependencies. But when you try to support multiple versions of rails, bundler might get confused.

Ideally, bundler should be able to automatically bundle(install) all the dependencies of our gem. And also dependencies of gem dependencies. example, bundle should be smart enough to figure out if rails v3.1 or v3.2 is required, it also needs to include sass-rails & 'uglifier' as they required by rails 3.1 & 3.2. But if rails v3.0 is required, nothing extra need to be done.

But we live in not so perfect world, so bundler is not smart enough. Hence, I think this is the reason active-admin has to resort to the following hack around bundler's shortcomings.

unless defined?(RAILS_VERSION_FILE)
  RAILS_VERSION_FILE = File.expand_path("../../../.rails-version", __FILE__)
end

unless defined?(DEFAULT_RAILS_VERSION)
  DEFAULT_RAILS_VERSION = "3.1.0"
end

def detect_rails_version
  return DEFAULT_RAILS_VERSION unless File.exists?(RAILS_VERSION_FILE)
  File.read(RAILS_VERSION_FILE).chomp
end

def write_rails_version(version)
  File.open(RAILS_VERSION_FILE, "w+"){|f| f << version }
end


rails_version = detect_rails_version
gem 'rails', rails_version

case rails_version
when /^3\.0/
  # Do nothing, bundler should figure it out
when /^3\.(1|2)/
  # These are the gems you have to have for Rails 3.1 to be happy
  gem 'sass-rails'
  gem 'uglifier'
else
  raise "Rails #{rails_version} is not supported yet"
end

if you notice the above code, it checks if current version of rails is v3.1 or v3.2. if yes, then add new two as dependencies. That's all this code does.


[Update]

Questions 1. what happens when application gems and gems' gem conflicts? If they conflict in such a way that bundler can't find a compatible version that satisfies dependencies of your app and gems. bundler will fail with an error something similar to this:

Bundler could not find compatible versions for gem "json":
  In Gemfile:
    chef (~> 10.26) ruby depends on
      json (<= 1.7.7, >= 1.4.4) ruby

    berkshelf (~> 2.0) ruby depends on
      json (1.8.0)

Question 2. Can we use active-admin standalone without rails? No. when you do gem install active-admin, rubygems will auto install rails as its listed as a dependency of this gem in gemspec file.

Upvotes: 1

Related Questions