Extending a model's class methods via a gem - ruby

I'm trying to write a gem that will allow me to call class methods on Rails models. So far, I have the following:
mygem/models/active_record_extension.rb
module ActiveRecordExtension
extend ActiveSupport::Concern
module ClassMethods
def foo
"foo"
end
end
end
# Include the extension
ActiveRecord::Base.send(:include, ActiveRecordExtension)
I'm requiring this file as follows:
require "mygem/version"
require "mygem/models/active_record_extension"
require "mygem/railtie" if defined? Rails
module MyGem
# Code goes here...
end
my gemspec file is including the necessary files:
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
spec.files = Dir["{lib}/**/*.rb"]
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.9"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_development_dependency "rspec", "~> 3.0"
spec.add_development_dependency "rails", "~> 4.2"
I've tried various variations on this but for some reason or another I cannot seem to be able to call .foo on a given model. I am currently getting a NameError: uninitialized constant ActiveRecordExtension::ActiveSupport. Am I going about this incorrectly?
Thanks!

Related

gemspec is broken, cli won't run

I keep running into a problem, this gemspec is invalid. Can someone please help me?
lib = File.expand_path("../lib", __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require "Practical/version"
Gem::Specification.new do |spec|
spec.name = "Practical"
spec.version = Practical::VERSION
spec.authors = ["'D'"]
spec.email = ["'#gmail.com'"]
spec.summary = %q{TODO: Write a short summary, because
RubyGems requires one.}
spec.description = %q{TODO: Write a longer description or delete
this line.}
spec.homepage = "TODO: Put your gem's website or public repo
URL here."
spec.license = "MIT"
# Prevent pushing this gem to RubyGems.org. To allow pushes either
set the 'allowed_push_host'
# to allow pushing to a single host or delete this section to allow
pushing to any host.
if spec.respond_to?(:metadata)
spec.metadata["allowed_push_host"] = "TODO: Set to
'http://mygemserver.com'"
spec.metadata["homepage_uri"] = spec.homepage
spec.metadata["source_code_uri"] = "TODO: Put your gem's public repo
URL here."
spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md
URL here."
else
raise "RubyGems 2.0 or newer is required to protect against "
"public gem pushes."
end
# Specify which files should be added to the gem when it is
released.
# The `git ls-files -z` loads the files in the RubyGem that have
been added into git.
spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
`git ls-files -z`.split("\x0").reject { |f|
f.match(%r{^(test|spec|features)/}) }
end
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f|
File.basename(f) }
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.17"
spec.add_development_dependency "rake", "~> 10.0"
spec.add_dependency "nokogiri"`enter code here`
end
I'm not sure what changed. This worked a few months ago, but now it's broken. Basically, I'm stuck just getting this to run, the interpreter keeps telling me I have an error in my gemspec. I can't find it.

Require in gem don't work

I created gem with bundler and puts all my ruby files into '/lib' as documentation suggested.
But I have a problem, after build the gem which "rake build" command and install (gem install pkg/gem) I can't use it because:
LoadError: cannot load such file -- mygem/client
this is cause because in main file i try to require 'mygem/client.rb' which is in lib/mygem/client.rb
and it is doesn't work :/
This is my gemspec:
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'diggy/version'
Gem::Specification.new do |spec|
spec.name = "diggy"
spec.version = Diggy::VERSION
spec.authors = [""]
spec.email = [""]
spec.summary = %q{: Write a short summary, because Rubygems requires one.}
spec.description = %q{: Write a longer description or delete this line.}
spec.homepage = ""
# Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host'
# to allow pushing to a single host or delete this section to allow pushing to any host.
if spec.respond_to?(:metadata)
spec.metadata['allowed_push_host'] = "TODO: Set to 'http://mygemserver.com'"
else
raise "RubyGems 2.0 or newer is required to protect against " \
"public gem pushes."
end
spec.files = `git ls-files -z`.split("\x0")
spec.bindir = "exe"
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.14"
spec.add_development_dependency "rake", "~> 10.0"
end
Assuming your main file is named mygem.rb and is inside the lib folder, you should be able to require the file lib/mygem/client.rb with:
require 'mygem/client'
Notice that I didn't use the .rb extension.

ruby: gem build... how do i include vendor directory in gem?

I run gem build mygem.gemspec and the vendor dir is not included. How do I include it in my gem? I am assuming that I need the vendor dir included if I want to package all the dependencies with my gem.
I think it has to do with Dir['vendor/**']... I know that is wrong.
My gemspec file:
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'fpa/fix_filename/version'
Gem::Specification.new do |spec|
spec.name = "fpa-fix_filename"
spec.version = Fpa::FixFilename::VERSION
spec.authors = ["na"]
spec.email = ["na"]
spec.summary = %q{A Class to fix bad file names -- includes a binary for command line use.}
spec.description = %q{}
spec.license = "MIT"
spec.files = Dir['lib/fpa/**/*'] + Dir['bin/*'] + Dir['vendor/**']
spec.bindir = "bin"
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.require_paths = ["lib"]
spec.add_runtime_dependency "micro-optparse", "~> 1.2.0"
spec.add_development_dependency "bundler", "~> 1.8"
spec.add_development_dependency "rake", "~> 10.0"
end
Did you tried like this ?
Dir['vendor/**/*']

Cannot get my Articles controller to create a blog Article with a picture. I am using imagemagick and carrierwave

My create action in ArticlesController seems fine if I create an Article without uploading a picture. However, if I try to upload a picture for an article, I get the error:
ActionController::UrlGenerationError in ArticlesController#create
No route matches {:action=>"show", :controller=>"articles", :id=>nil} missing required keys: [:id]
Here is my Articles controller:
class ArticlesController < ApplicationController
before_filter :require_login, only: [:new, :create, :edit, :update, :destroy]
def index
#articles = Article.all
end
def show
#article = Article.find(params[:id])
#comment = Comment.new
#comment.article_id = #article.id
end
def new
#article = Article.new
end
def create
#article = Article.new(article_params)
#article.save
redirect_to article_path(#article)
end
def edit
#article = Article.find(params[:id])
end
def destroy
#article = Article.find(params[:id])
#article.destroy
redirect_to articles_path
end
def update
#article = Article.find(params[:id])
#article.update(article_params)
flash.notice = "Article '#{#article.title}' Updated!"
redirect_to article_path(#article)
end
private
def article_params
params.require(:article).permit(:title, :body, :tag_list, :picture)
end
end
Here is my Article model:
class Article < ActiveRecord::Base
has_many :comments
has_many :taggings
has_many :tags, through: :taggings
mount_uploader :picture, PictureUploader
validate :picture_size
def tag_list
self.tags.collect do |tag|
tag.name
end.join(", ")
end
def tag_list=(tags_string)
tag_names = tags_string.split(",").collect{|s| s.strip.downcase}.uniq
new_or_found_tags = tag_names.collect { |name| Tag.find_or_create_by(name: name) }
self.tags = new_or_found_tags
end
# Validates the size of an uploaded picture.
def picture_size
if picture.size > 5.megabytes
errors.add(:picture, "should be less than 5MB")
end
end
end
My Gemfile :
source 'http://rubygems.org'
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails'
gem 'rails', '4.1.8'
# Use sqlite3 as the database for Active Record
gem 'sqlite3'
# Use SCSS for stylesheets
gem 'sass-rails', '~> 4.0.3'
# Use Uglifier as compressor for JavaScript assets
gem 'uglifier', '>= 1.3.0'
# Use CoffeeScript for .js.coffee assets and views
gem 'coffee-rails', '~> 4.0.0'
# See https://github.com/sstephenson/execjs#readme for more supported runtimes
# gem 'therubyracer', platforms: :ruby
gem 'carrierwave', '0.10.0'
gem 'mini_magick', '~> 4.0.4'
gem 'fog', '~> 1.27.0'
# Use jquery as the JavaScript library
gem 'jquery-rails'
# Turbolinks makes following links in your web application faster. Read more: https://github.com/rails/turbolinks
gem 'turbolinks'
# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder
gem 'jbuilder', '~> 2.0'
gem 'sorcery'
# bundle exec rake doc:rails generates the API under doc/api.
gem 'sdoc', '~> 0.4.0', group: :doc
# Use ActiveModel has_secure_password
gem 'bcrypt', '~> 3.1.7'
# Use unicorn as the app server
# gem 'unicorn'
# Use Capistrano for deployment
# gem 'capistrano-rails', group: :development
# Use debugger
# gem 'debugger', group: [:development, :test]
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin]
And finally my picture uploader:
# encoding: utf-8
class PictureUploader < CarrierWave::Uploader::Base
# Include RMagick or MiniMagick support:
# include CarrierWave::RMagick
include CarrierWave::MiniMagick
process resize_to_limit: [500, 500]
if Rails.env.production?
storage :fog
else
storage :file
end
# Override the directory where uploaded files will be stored.
# This is a sensible default for uploaders that are meant to be mounted:
def store_dir
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
end
# Provide a default URL as a default if there hasn't been a file uploaded:
# def default_url
# # For Rails 3.1+ asset pipeline compatibility:
# # ActionController::Base.helpers.asset_path("fallback/" + [version_name, "default.png"].compact.join('_'))
#
# "/images/fallback/" + [version_name, "default.png"].compact.join('_')
# end
# Process files as they are uploaded:
# process :scale => [200, 300]
#
# def scale(width, height)
# # do something
# end
# Create different versions of your uploaded files:
# version :thumb do
# process :resize_to_fit => [50, 50]
# end
# Add a white list of extensions which are allowed to be uploaded.
# For images you might use something like this:
def extension_white_list
%w(jpg jpeg gif png)
end
# Override the filename of the uploaded files:
# Avoid using model.id or version_name here, see uploader/store.rb for details.
# def filename
# "something.jpg" if original_filename
# end
end
What am I doing wrong with carrierwave and Imagemagic to get
this error ?

Problems with require in gem

I am trying to make a simple gem which has some modules. However, after I have built and installed the gem and try require it in a script I get an error:
from ...ruby-1.9.3-p429/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- my_gem/some_class (LoadError)
And
from ...ruby-1.9.3-p429/gems/my_gem-0.0.1/lib/my_gem.rb:2:in `<top (required)>'
Line 2 in my_gem.rb is require "my_gem/some_class.
As far as I understand (from this question) the problem seems to be that the file I require isn't found.
What is going on? Why can't I require my own files inside the gem?
The files I want to require is "next to" the version.rb.
#File Structure
#
# root
# |->lib
# | |->my_gem.rb
# | |->my_gem
# | | |->some_class.rb
# | | |->some_class2.rb
# | | |->version.rb
The SomeClass looks like this:
module MyGem
class SomeClass
def self.someMethod
...
end
end
All I do in the script where I get the error is the following:
#!/usr/bin/ruby
require "rubygems"
require "my_gem"
Gemspec:
# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'my_gem/version'
Gem::Specification.new do |spec|
spec.name = "my_gem"
spec.version = MyGem::VERSION
spec.authors = ["My Name"]
spec.email = ["my_email#gmail.com"]
spec.description = %q{A simple Ruby gem that fails.}
spec.summary = %q{Failing gem for Ruby.}
spec.homepage = "http://some.website.com"
spec.license = "MIT"
spec.files = `git ls-files`.split($/)
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
spec.require_paths = ["lib"]
spec.add_development_dependency "bundler", "~> 1.3"
spec.add_development_dependency "rake"
end
It looks like you have not added your class files to git, while your Gemspec file uses common pattern to specify files to be added to gem:
spec.files = `git ls-files`.split($/)
You have two options not to run into same trouble again:
Add all the files to version control before building a gem;
Use hand-written spec.files list in Gemspec.
Or, if you are using svn, you might want to change the spec.files to:
spec.files = `svn list`.split($/)
Hope it helps.

Resources