"Attaching" a gem to Rails to prevent "require" everywhere? - ruby-on-rails

The name of a gem is not the same as the module. Right now I need to require it and include in various types of files, such as controllers and models. This is amounting to many requires which I don't have to do for other gems. It's a gem I can update. Is there a way the gem needs to be configured so it is "attached" to Rails, and if so, where may I find instructions to do this?
UPDATE: using required: "name-of-module" in Gemfile removes need for require everywhere. Still wondering, if gem could be configured to not require this in Gemfile?

In the Gemfile, you can do these things:
# Require a different file than the gem's name
gem 'foo', require: 'bar'
# Install but not require anything.
# You need to manually require the gem somewhere.
gem 'foo', require: false
You can still add version and platform specification if you want.
Real-world examples are ActiveSupport and rspec:
gem 'activesupport', '~> 5.2', require: 'active_support/all'
gem 'rspec', '~> 3.1', group: :test, require: false

You need to specify which files you want Ruby to load for you, so you either need specify the gem in your Gemfile (and run bundle exec ...) or put require in the right place(s) in your code. There's no way around that.
If it's a gem that you work on at the same time as you use it in another project, then you can specify a path to the gem. Like
# Gemfile
source "https://rubygems.org"
ruby '2.6.1'
gem 'my_gem', path: '/home/user/Development/my_gem'
This way, you can change your gem and use it directly without having to build and install it.

Related

Why does Rails not correctly unescape escaped strings in my fixtures?

I have a weird thing going on where I tried to update to Ruby 2.3.1, but now a test fails. The test which fails seems like the broken data is in the Rails fixtures, as opposed to being a real failure.
In the fixture, I have:
one:
name: "\u30C6\u30B9\u30C8"
When I look at this value in the console, it seems like it has been double-escaped:
irb(main):001:0> Organisation.first.name
Organisation Load (0.1ms) SELECT "organisations".* FROM "organisations" ORDER BY "organisations"."id" ASC LIMIT 1
=> "\\u30C6\\u30B9\\u30C8"
This is also exactly what I saw when I debugged the tests themselves.
Known so far:
If I downgrade back to to Ruby 2.1.2, I see the proper unescaped value.
If I downgrade to Ruby 2.2.2, the issue still occurs.
If I load the exact same file using YAML.load on Ruby 2.3.1, I see the proper unescaped value.
If I create a brand new Rails application and copy the exact same fixture lines over, I see the proper unescaped value.
What could possibly be going on here? Is some other gem interfering with parsing YAML, but only when loaded using whatever Rails is using to load fixtures? How does Rails load fixtures which makes it not work even though YAML.load appears to work fine?
Rails is version 4.2.6.
Other gems in use:
gem 'rails', '~> 4.2.0'
gem 'sqlite3'
gem 'mysql2', platforms: %w( ruby )
group :development do
gem 'capistrano', git: 'git://github.com/trejkaz/capistrano'
gem 'capistrano-rails'
gem 'capistrano-rbenv'
end
gem 'uglifier'
gem 'execjs'
gem 'therubyracer'
group :development, :test do
gem 'byebug'
end
gem 'rails3-restful-authentication', require: 'restful_authentication'
gem 'strip_attributes'
gem 'dynamic_form'
gem 'will_paginate'
gem 'acts_as_list'
gem 'jquery-tokeninput-rails'
gem 'jquery-rails'
gem 'jquery-ui-rails'
gem 'exception_notification', '~> 4.0.0'
gem 'syck', '~> 1.0.0'
group :development, :test do
gem 'simplecov'
gem 'ci_reporter_minitest'
gem 'mocha'
gem 'metric_fu'
gem 'flog', '~> 4.3.2'
end
Digging inside ActiveRecord, the low-level fixture reading code is definitely doing the wrong thing somehow...
irb(main):014:0> ActiveRecord::FixtureSet::File.open('test/fixtures/organisations.yml') { |fh| fh.each { |fixture_name, row| puts fixture_name; puts row } }
one
{"name"=>"\\u30C6\\u30B9\\u30C8"}
=> [["one", {"name"=>"\\u30C6\\u30B9\\u30C8"}]]
Behaviour of loading YAML differs depending on whether you just load irb, or use the rails console... So it does seem like something else in the environment messes up reading YAML somehow. :(
$ irb
irb(main):001:0> require 'yaml'
=> true
irb(main):002:0> YAML.load_file('test/fixtures/organisations.yml')
=> {"six"=>{"name"=>"ใƒ†ใ‚นใƒˆ"}}
irb(main):003:0>
$ bundle exec rails console
Loading development environment (Rails 4.2.6)
irb(main):001:0> YAML.load_file('test/fixtures/organisations.yml')
=> {"six"=>{"name"=>"\\u30C6\\u30B9\\u30C8"}}
irb(main):002:0>
I would blame syck - this is the yaml parser from pre ruby 1.9.3 (although it was I believe still available in later versions just not the default) made available as a gem for those who depend on it. To quote the "problems" section from the gem's readme
Monkeypatches the crap out of everything
Unless you have some very particular legacy code you almost certainly don't need it. Its replacement (psych) is part of the ruby standard library.

Gemfile styling

I would like to know if there is a generally accepted style on Gemfile.
I generate new rails application, open the Gemifile, and add all the gems I need under appropriate group (test, dev etc.).
When I look at Rails opensource projects, most are not structured this way. They have the standard installed Rails gems left as they are or commented out, and then there is a second list of gems under it for the gems that the app actually needs. For me, this is less readable, but is there a reason why a lot of people seem to do it this way?
There is no general standard or consensus, exactly like there is no general standard on leaving commented code in a Ruby file.
Generally, the idea of leaving stuff commented out is a bad habit from the days where we were used to code without a version control system.
If you are not using a Gem, there is no need to leave it there commented out. It's fine to comment it out temporarily while testing different behaviours with/without or temporarily for whatever reason, but once you reached a decision to take out the gem it's safe to remove it.
Personally, I generally structure the Gemfiles in the following way:
source 'https://rubygems.org'
# Rails core gems at the top
gem 'rake'
gem 'rails', '4.2.5'
gem 'sass-rails', '~> 5.0'
.
.
.
gem 'responders', '~> 2.0'
# Gems, in alphabetical order
gem 'yajl-ruby', '~> 1.2.0', require: 'yajl'
gem 'bcrypt', '~> 3.1.0', require: 'bcrypt'
.
.
.
# Environment dependent gems, in alphabetical order
group :test do
gem 'database_cleaner', require: false
.
.
end
group :development do
gem 'letter_opener', '~> 1.4.0'
.
.
.
end
group :production do
gem 'clockwork', '~> 1.2.0', require: false
.
.
.
end
group :development, :test do
gem 'byebug', require: false
.
.
.
end

How to add dependency to gemfile.lock through gemspec?

Personnel in relation to add_runtime_dependency, add_dependency and add_development_dependency the "Gem Specification", I'm trying to understand them. How they work and how to differentiate them.
When I used the add_development_dependency, I was unable to observe anything different. When I used the add_dependency and also the add_runtime_dependency, the same effect was observed.
It was added to gemfile.lock as the only dependence of my gem, but not a project dependency. And I would like it to be added as a project dependency, because I think add redundant as a unit of my gem, and dependence of the project, adding it to the Gemfile.
What I do not understand is that if I add the jquery as a unit of my gem, but don't add it directly in the application Gemfile, it is not found. I get the following error.
"could not find file 'jquery'".
You should not gemfile.lock manually. You should include jquery-rails in Gemfile and do bundle install. gemfile.lock is managed by bundler. If you need dependencies only in a given environment you can do something like.
group :development do
gem 'better_errors'
gem 'bullet'
gem 'lol_dba'
gem 'meta_request'
gem 'pry-rails'
gem 'rbeautify'
gem 'rsense'
gem 'rubocop'
gem 'spring'
gem 'ruby-growl'
end
group :development, :test do
gem 'binding_of_caller'
gem 'jazz_hands'
end
Anything not in a specific group will be included in all environments.

Conditions on gem requirement

I would like to prevent the updating of a gem on my windows (rmagick), so it sticks to 2.12.0 mswin32. Still, my coworker needs to have the gem on his Darwin install...
So, I tried to do something like this in the Gemfile:
if RUBY_PLATFORM =~ /darwin/i
gem 'rmagick', '~> 2.12.0'
else
gem 'rmagick', '=2.12.0.mswin32'
end
but bundle install complaints.
What is the right way of handling this properly?
You can't use conditionals on gemspec because gemspec is serialized
into YAML, which doesn't contain executable code.
I faced a related problem in the Gemfile of a local Rails project (not a
gem).
Currently, the Gemfile contains:
group :test do
...
# on Mac os X
gem 'rb-fsevent' if RUBY_PLATFORM.include?("x86_64-darwin")
gem 'ruby_gntp' if RUBY_PLATFORM.include?("x86_64-darwin")
# on Linux
gem 'rb-inotify' unless RUBY_PLATFORM.include?("x86_64-darwin")
gem 'libnotify' unless RUBY_PLATFORM.include?("x86_64-darwin")
end
This works (although it is ugly) for developing on Mac and Linux
systems.
But, we stopped checking in the Gemfile.lock since it changes every time
a developer with a different platform checks in the code.
So, a solution for multi-platform Gemfiles should also solve the
problem for Gemfile.lock.
The other solutions is building multiple .gemspec files for each target OS and change both platform and dependencies for each platform:
gemspec = Gem::Specification.new do |s|
s.platform = Gem::Platform::RUBY
end
# here build the normal gem
# Now for linux:
gemspec.platform = "linux"
gemspec.add_dependency ...
# build the newer gemspec
...
You should use the platforms option Bundler provides:
If a gem should only be used in a particular platform or set of
platforms, you can specify them. Platforms are essentially identical
to groups, except that you do not need to use the --without
install-time flag to exclude groups of gems for other platforms.
So in your specific case that would look something like this:
gem 'rmagick', '~> 2.12.0', :platforms => :ruby
gem 'rmagick', '=2.12.0.mswin32', :platforms => :mswin

Launching RoR server for an existing app gives error

I just made my first setup of RoR, and creating a new application works fine. But when I want to run the rails server I get the following error:
C:/Ruby192/lib/ruby/gems/1.9.1/gems/delayed_job-2.1.3/lib/delayed/yaml_ext.rb:30:in 'remove_method': method 'to_yaml' not defined in Class (NameError)
I ran the "bundle install" in the app directory and installed all the necessary files (with some problems however, but I excluded the gems with problems in the gemfile) and the last bundle install said that I have successfully installed all the needed packs.
I'm lost and I can't find a similar error on the internet. Can you help me?
EDIT: I forgot to mention that I'm not having a problem with a new application. It's running an existing one (that I didn't build, but works fine for others) that the error is related to. Here's the gemfile for that app:
source 'http://rubygems.org'
gem 'rails', '3.0.3'
gem 'mysql'
gem "haml", ">= 3.0.0"
gem "haml-rails"
gem 'simple_form'
gem 'delayed_job'
#gem 'auto_crawlers'
gem 'will_paginate', '~> 3.0.beta'
group :test do
gem 'factory_girl_rails'
gem 'mocha'
end
group :development do
#gem "nifty-generators", "0.4.3", :git => "git://github.com/JonasNielsen/nifty-generators.git"
gem 'fastercsv'
end
gem "mocha", :group => :test
Do you think the error is because I left out the two gems with "#" ? Those were causing problems at first, and I don't think I need them to test some minor changes in the app (some views that I have to modify)
The issue is being described, and supposedly fixed here: https://github.com/collectiveidea/delayed_job/issuesearch?state=open&q=yaml#issue/194
Try this from the command line: irb -rubygems -r delayed_job and then from your bundled directory bundle-exec irb -rubygems -r delayed_job which will show if there is a difference between your system gems and your bundled setup - you might see an error in one or both attempts to run IRB.
If there is an error using bundle-exec but not with your system gems then it's a bundler issue. If not, are you sure the app is designed to function under Ruby 1.9? It looks like to_yaml isn't available at the point DJ is required, which implies it probably needs a require "yaml" somewhere.

Resources