I'm new to RoR and jumping into a big RoR project. The project uses a bunch of gems. In fact, the Gemfile.lock file, including dependencies, is 460 lines long. I was told the project went through several different developers, and that there may be a lot of cruft in there.
Is there any way to generate a list of what each gem does? It's not exactly intuitive, especially with names like "capybara" and "cocaine" and "raindrops."
Is there any simple process to determine which gems are required?
You really shouldn't stress too much about what's in the Gemfile.lock at first, just the Gemfile.
To get gem details, I just whipped this little script up to dump summaries of all the gems in your current bundle:
require 'yaml'
gems = `bundle list`
names = gems.scan(/^\s+\*\s+([\w-]+)\s+\(.*\)\s*$/).flatten
names.each do |name|
summary = YAML.parse(`gem spec #{name} summary`).root.value rescue '???'
puts "#{name}: #{summary}"
end
Save it to a file and run it on the command line like so:
ruby whatever-you-saved-it-as.rb
For a project of mine, I got this:
actionmailer: Email composition, delivery, and receiving framework (part of Rails).
actionpack: Web-flow and rendering framework putting the VC in MVC (part of Rails).
actionview: Rendering framework putting the V in MVC (part of Rails).
activemodel: A toolkit for building modeling frameworks (part of Rails).
activerecord: Object-relational mapper framework (part of Rails).
activesupport: A toolkit of support libraries and Ruby core extensions extracted from the Rails framework.
addressable: URI Implementation
annotate: Annotates Rails Models, routes, fixtures, and others based on the database schema.
arel: Arel is a SQL AST manager for Ruby
ast: A library for working with Abstract Syntax Trees.
astrolabe: An object-oriented AST extension for Parser
awesome_print: Pretty print Ruby objects with proper indentation and colors
...
Kinda neat actually.
Assuming that each gem has a meaningful description, you can run something like this from the Rails console:
Gem.loaded_specs.values.map { |g| "#{g.name}: #{g.summary}" }
The dynamic nature of Ruby makes it hard to find unused gems automatically (e.g. through code analysis). However, you can try to remove gems one by one. If your project's test suite passes without a given gem, it is certainly a strong sign that it might be safe to remove it.
Related
I frequently want to try out small code snippets, often much smaller than classes, and even functions, just to make sure it works by itself so I don't need to test it by running a bunch of scripts, simply to fix small errors in a line of code or so.
Besides irb/pry, I want to test Rails-specific code, such as Object.blank?. So with that, I want to have the Rails library loaded, but I don't need the full functionality that Rails console gives me. Especially when the application is not in a working state, the REPL will not open at all, and merely present a stack trace of the failure at hand.
If anybody knew how to achieve this middle ground, maybe through the use of a particular gem path and require statement to load one of the other REPLs I have mentioned, could you illustrate those commands?
I am working inside of a project using RVM to manage the gemset, and would like to not modify that environment at all, maybe only my general terminal environment, if possible.
.blank? is from ActiveSupport. You can actually just load ActiveSupport without the rest of Rails:
irb(main):001:0> require 'active_support/all'
irb(main):002:0> [].blank?
=> true
The all.rb file loads all of ActiveSupport.
The same can be done with ActiveRecord and other rails components; for example:
irb(main):001:0> require 'active_record'
=> true
irb(main):002:0> class NewModel < ActiveRecord::Base; end
=> nil
irb(main):003:0> NewModel.new
ActiveRecord::ConnectionNotEstablished: No connection pool for NewModel
This gives an error because I didn't bother setting up a database, but it shows that Rails is pretty modular. I've used ActiveRecord in projects without Rails (the rails gem is actually an empty gem which just defines the various active_* gems as dependencies).
Most of the Rails "magic" come from Active Support Core Extensions. You can include that in a regular irb session to get most of the connivence methods like blank?.
Start an IRB session and run
require 'active_support'
require 'active_support/core_ext'
I have been using the seedbank gem to give my Rails seeds some structure (i.e. environment specific seed folders, one seed file per model, order dependencies etc.)
Now I came across the seed_fu gem which among other things makes it easy and expressive to say "seed these records, and if one with that id exists, update the other fields". E.g:
Category.seed(:id,
{ :id => 1, :name => "Food" },
{ :id => 2, :name => "Drink" }
)
I can achieve the same result with some cumbersome ActiveRecord calls in my seed files, but I would much rather use the nice syntax provided by seed_fu. Additionally, I want to keep using the features seedbank gives me. Another rationale is that I may migrate only part of my seed files to the other syntax and that it makes no sense to use two rake commands side by side.
If I just put the above code in my db/seeds/categories.seeds.rb file and run rake db:seed:categories i get the error undefined method 'seed'. I guess I would somehow need to import the seed method from SeedFu:ActiveRecordExtension, but I don't know how.
I'm on Rails 3.2.13 and using the newest version of seed_fu straight from the github repo.
Short answer: seed_fu and seedbank work together without any problem.
I was using the zeus gem and hadn't reloaded my Rails environment so the seed_fu DSL just wasn't loaded yet.
(I will leave the question here for anyone wondering if you can use these gems together. TL;DR: yes.)
I am trying to generate a resource and I have removed all references to Active_record and removed the databse.yml file.
The rails server starts ok but when I try to generate a model:
rails g resource contact
I get the following error:
No value provided for required options '--orm'
Is there a way to specify no database when generating a resource?
There isn't an easy way, no. If you look at the source code for the resource generator, you'll see this part regarding the orm:
# Loads the ORM::Generators::ActiveModel class. This class is responsible
# to tell scaffold entities how to generate an specific method for the
# ORM. Check Rails::Generators::ActiveModel for more information.
def orm_class
#orm_class ||= begin
# Raise an error if the class_option :orm was not defined.
unless self.class.class_options[:orm]
raise "You need to have :orm as class option to invoke orm_class and orm_instance"
end
begin
"#{options[:orm].to_s.camelize}::Generators::ActiveModel".constantize
rescue NameError
Rails::Generators::ActiveModel
end
end
end
So it explicitly rejects any attempt to run this command without an ORM, and if you do specify an ORM, it's looking for ORM::Generators::ActiveModel. And in the comments at the top, it specifies a location to find more information, Rails::Generators::ActiveModel. The comments at the top there explain how to extend it to create an ORM specification.
The only one built-in to rails by default is the ActiveRecord generator.
There is a gem called rails3-generators that includes generators for a number of common libraries, but you can see that for ORMs it only adds functionality for data_mapper, mongo_mapper, mongoid, and active_model.
As far as I know, there is no pre-built ORM generator for "no database". You could write one yourself, if you want, by following the instructions at the top of Rails::Generators::ActiveModel (and using the rails3-generators gem source as a reference of you need it).
But if that seems like too much effort, I'd recommend just telling it to generate using the built-in ActiveRecord generator, and then just manually modifying/removing anything it generated related to that ORM.
Before I ask a question, I like to caution everyone that I am a programming newbie, so please correct me if I ask something ridiculous.
I have been reading about Ruby having open classes, i.e a method can be added. However, I am trying to get a few examples of how Rails might have added to existing Ruby classes.
Rails has so many core extensions they're in a separate gem – ActiveSupport.
No sense trying to explain everything here, I'll just point you to the Rails guides. After you are familiar with them, refer to the documentation when you need to.
I second Matheus. ActiveSupport is a good example. Take a look at some source code files here:
https://github.com/rails/rails/tree/master/activesupport/lib/active_support/core_ext
And, here's a typical and simplistic example which adds useful and somewhat controversial methods on standard Array class in Ruby.
https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/array/access.rb
Most Ruby libraries have a directory named 'core_ext', 'ext' or something along this line which includes methods that extend Ruby's core library in a way or another. People always reinvent methods and in a sense, ActiveSupport is the definitive compilation of those.
I have found that a great example is Time
From a rails application
Time.
Loading development environment (Rails 3.2.3)
1.9.3p125 :001 > Time.
Display all 252 possibilities? (y or n)
Time.module_exec
Time.__delay__ Time.mongo_thread_local_accessor
Time.__id__ Time.name
...
Total = 252
From a plain ruby console (IRB)
$ irb
1.9.3p125 :001 > Time.
Time.hash Time.private_method_defined?
Time.__id__ Time.include? Time.private_methods
Time.__send__ Time.included_modules Time.protected_instance_methods
...
Total = 93
I am a beginner in Rails. I use 2.3.X.
I just saw Rails 3 is pre-released [edit: now in release candidate!]. I will most probably eventually switch to it.
What are the common coding habits in 2.3 I should not take, so that the switch is as smooth as possible ?
Edit:
I've done my homework and read the Release notes. But they are far from clear for the most crucial points, for example :
1.5 New APIs
Both the router and query interface have seen significant, breaking changes. There is a backwards compatibility layer that is in place and will be supported until the 3.1 release.
This is not comprehensive enough for a beginner like me. What will break ? What could I do already in 2.3.X to avoid having troubles later ?
Looking at my personal coding habits (I have been using Rails since 1.2.x), here's a list of API changes you can anticipate according to Rails 3 release notes.
find(:all)
Avoid the usage of:
Model.find(:all)
Model.find(:first)
Model.find(:last)
in favour of:
Model.all
Model.first
Model.last
Complex queries
Avoid the composition of complex queries in favor of named scopes.
Anticipate Arel
Rails 3 offers a much cleaner approach for dealing with ActiveRecord conditions and options. You can anticipate it creating custom named scopes.
class Model
named_scope :limit, lambda { |value| { :limit => value }}
end
# old way
records = Model.all(:limit => 3)
# new way
records = Model.limit(3).all
# you can also take advantage of lazy evaluation
records = Model.limit(3)
# then in your view
records.each { ... }
When upgrading to Rails 3, simply drop the named scope definition.
Constants
Avoid the usage of the following constants in favour of the corresponding Rails.x methods, already available in Rails 2.x.
RAILS_ROOT in favour of Rails.root,
RAILS_ENV in favour of Rails.env, and
RAILS_DEFAULT_LOGGER in favour of Rails.logger.
Unobtrusive Javascript
Avoid heavy JavaScript helpers in favour of unobtrusive JavaScript.
Gem dependencies
Keep your environment.rb as clean as possible in order to make easier the migration to Bundler. You can also anticipate the migration using Bundler today without Rails 3.
The release notes are the most important thing to keep an eye on. Other than that Jeremy McAnally has some neat blog posts about the whole Rails 3 thing (and has just released a gem to help you with the migration).
I'd say, read the rails release notes and see for yourself what seems the more surprising to you. A lot of stuff changed so reading this is definitively very important.