Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Integração de gems com o Rails @ RS on Rails

Integração de gems com o Rails @ RS on Rails

77237b97a465ae5a293ad323b7296837?s=128

Carlos Antonio

September 15, 2012
Tweet

Transcript

  1. Railties INTEGRANDO GEMS COM O RAILS

  2. @cantoniodasilva Carlos Antonio

  3. None
  4. Devise maintainer

  5. SimpleForm maintainer

  6. Responders maintainer

  7. Rails commiter

  8. guru SC

  9. Railties INTEGRANDO GEMS COM O RAILS

  10. The Road So Far...

  11. Rails 2.3

  12. Plugins! vendor/plugins

  13. script/plugin install git://github.com/SomeGuy/ my_awesome_plugin.git

  14. Engines! app/*

  15. App Engine

  16. module Rails class Plugin # Engines are plugins with an

    app/ directory. def engine? has_app_directory? end private def has_app_directory? File.directory?(File.join(directory, 'app')) end end end https://github.com/rails/rails/blob/2-3-stable/railties/lib/rails/plugin.rb
  17. module Rails class Plugin # Engines are plugins with an

    app/ directory. def engine? has_app_directory? end private def has_app_directory? File.directory?(File.join(directory, 'app')) end end end https://github.com/rails/rails/blob/2-3-stable/railties/lib/rails/plugin.rb # Engines are plugins with an app/ directory. def engine? has_app_directory? end private def has_app_directory? File.directory?(File.join(directory, 'app')) end
  18. None
  19. app/ models controllers helpers config/ routes.rb

  20. module Rails class Plugin def view_path File.join(directory, 'app', 'views') end

    def controller_path File.join(directory, 'app', 'controllers') end def routing_file File.join(directory, 'config', 'routes.rb') end private def app_paths [ File.join(directory, 'app', 'models'), File.join(directory, 'app', 'helpers'), controller_path, metal_path ] end end end https://github.com/rails/rails/blob/2-3-stable/railties/lib/rails/plugin.rb
  21. module Rails class Plugin def view_path File.join(directory, 'app', 'views') end

    def controller_path File.join(directory, 'app', 'controllers') end def routing_file File.join(directory, 'config', 'routes.rb') end private def app_paths [ File.join(directory, 'app', 'models'), File.join(directory, 'app', 'helpers'), controller_path, metal_path ] end end end https://github.com/rails/rails/blob/2-3-stable/railties/lib/rails/plugin.rb def view_path File.join(directory, 'app', 'views') end def controller_path File.join(directory, 'app', 'controllers') end def routing_file File.join(directory, 'config', 'routes.rb') end private def app_paths [ File.join(directory, 'app', 'models'), File.join(directory, 'app', 'helpers'), controller_path, metal_path ] end
  22. Rails Active Record

  23. module Rails class Initializer def load_observers if gems_dependencies_loaded && configuration.frameworks.include?(:active_record)

    ActiveRecord::Base.instantiate_observers end end def initialize_database if configuration.frameworks.include?(:active_record) ActiveRecord::Base.configurations = configuration.database_configuration ActiveRecord::Base.establish_connection end end end end https://github.com/rails/rails/blob/2-3-stable/railties/lib/initializer.rb
  24. module Rails class Initializer def load_observers if gems_dependencies_loaded && configuration.frameworks.include?(:active_record)

    ActiveRecord::Base.instantiate_observers end end def initialize_database if configuration.frameworks.include?(:active_record) ActiveRecord::Base.configurations = configuration.database_configuration ActiveRecord::Base.establish_connection end end end end https://github.com/rails/rails/blob/2-3-stable/railties/lib/initializer.rb if gems_dependencies_loaded && configuration.frameworks.include?(:active_record) ActiveRecord::Base.instantiate_observers end if configuration.frameworks.include?(:active_record) ActiveRecord::Base.configurations = configuration.database_configuration ActiveRecord::Base.establish_connection end
  25. module Rails class Initializer private def default_frameworks [ :active_record, :action_controller,

    :action_view, :action_mailer, :active_resource ] end end end https://github.com/rails/rails/blob/2-3-stable/railties/lib/initializer.rb
  26. module Rails class Initializer private def default_frameworks [ :active_record, :action_controller,

    :action_view, :action_mailer, :active_resource ] end end end https://github.com/rails/rails/blob/2-3-stable/railties/lib/initializer.rb def default_frameworks [ :active_record, :action_controller, :action_view, :action_mailer, :active_resource ] end
  27. ORMs

  28. ORMs Sequel MongoMapper DataMapper Mongoid

  29. Frágil

  30. monkey Patch

  31. module Rails class Initializer def process Rails.configuration = configuration check_ruby_version

    install_gem_spec_stubs set_load_path add_gem_load_paths require_frameworks set_autoload_paths add_plugin_load_paths load_environment preload_frameworks initialize_encoding initialize_database initialize_cache initialize_framework_caches initialize_logger initialize_framework_logging initialize_dependency_mechanism initialize_whiny_nils initialize_time_zone initialize_i18n initialize_framework_settings initialize_framework_views initialize_metal add_support_load_paths check_for_unbuilt_gems load_gems load_plugins https://github.com/rails/rails/blob/2-3-stable/railties/lib/initializer.rb # pick up any gems that plugins depend on add_gem_load_paths load_gems check_gem_dependencies # bail out if gems are missing - note that check_gem_dependencies # will have already called abort() unless $gems_rake_task is set return unless gems_dependencies_loaded load_application_initializers # the framework is now fully initialized after_initialize # Setup database middleware after initializers have run initialize_database_middleware # Prepare dispatcher callbacks and run 'prepare' callbacks prepare_dispatcher # Routing must be initialized after plugins to allow the former to # extend the routes initialize_routing # Observers are loaded after plugins in case Observers or observed # models are modified by plugins. load_observers # Load view path cache load_view_paths # Load application classes load_application_classes # Disable dependency loading during request cycle disable_dependency_loading # Flag initialized Rails.initialized = true end end end
  32. Single Responsibility Principle

  33. Single Responsibility Principle

  34. Rails 3

  35. Modularidade

  36. Rails Active Record

  37. Rails Active Record

  38. Rails

  39. Rails Action Controller Action Mailer Action View Active Record Active

    Resource
  40. Rails

  41. Rails DataMapper Devise RSpec Mongoid etc...

  42. Hooks!

  43. Rails:: Railtie

  44. Configuração & Inicialização

  45. Config

  46. module Responders class Railtie < ::Rails::Railtie config.responders = ActiveSupport::OrderedOptions.new config.responders.flash_keys

    = [ :notice, :alert ] # ... end end https://github.com/plataformatec/responders/blob/v0.9.2/lib/responders.rb Responders
  47. module MyApp class Application < ::Rails::Application config.responders.flash_keys = [ :success,

    :failure ] end end
  48. Initializers

  49. module Responders class Railtie < ::Rails::Railtie config.responders.flash_keys = [ :notice,

    :alert ] initializer "responders.flash_responder" do |app| Responders::FlashResponder.flash_keys = app.config.responders.flash_keys # ... end end end https://github.com/plataformatec/responders/blob/v0.9.2/lib/responders.rb Responders
  50. module CarrierWave class Railtie < Rails::Railtie initializer "carrierwave.setup_paths" do CarrierWave.root

    = Rails.root.join(Rails.public_path).to_s # ... end end end https://github.com/jnicklas/carrierwave/blob/v0.6.2/lib/carrierwave.rb CarrierWave
  51. Initializers + Hooks

  52. module MyGem class Railtie < Rails::Railtie config.before_configuration { # Executa

    antes das configurações do usuário } end end
  53. module MyGem class Railtie < Rails::Railtie config.before_initialize { # Depois

    da config do usuário, mas antes dos # initializers. } end end
  54. module MyGem class Railtie < Rails::Railtie config.to_prepare { # cache_classes

    = false (development) # Roda toda vez antes de recarregar o ambiente. # cache_classes = true (production) # Roda antes da primeira requisição. } end end
  55. module MyGem class Railtie < Rails::Railtie config.before_eager_load { # Antes

    de carregar todo o código da aplicação, # somente com cache_classes true. } end end
  56. module MyGem class Railtie < Rails::Railtie config.after_initialize { # Após

    todos os demais (configs, initializers, etc), # uma única vez antes da primeira requisição. } end end
  57. Development before_configuration => Booting WEBrick before_initialize to_prepare after_initialize [...] INFO

    WEBrick 1.3.1 to_prepare Request... to_prepare Request... to_prepare Production (cache_classes) before_configuration => Booting WEBrick before_initialize to_prepare before_eager_load after_initialize [...] INFO WEBrick 1.3.1 Request... Request...
  58. Development before_configuration => Booting WEBrick before_initialize to_prepare after_initialize [...] INFO

    WEBrick 1.3.1 to_prepare Request... to_prepare Request... to_prepare Production (cache_classes) before_configuration => Booting WEBrick before_initialize to_prepare before_eager_load after_initialize [...] INFO WEBrick 1.3.1 Request... Request...
  59. module ActiveRecord class Railtie < Rails::Railtie config.after_initialize do ActiveSupport.on_load(:active_record) do

    instantiate_observers ActionDispatch::Reloader.to_prepare do ActiveRecord::Base.instantiate_observers end end end end end https://github.com/rails/rails/tree/3-2-stable/activerecord/lib/active_record/railtie.rb Active Record
  60. module Rails module Mongoid class Railtie < Rails::Railtie initializer "instantiate

    observers" do config.after_initialize do ::Mongoid::instantiate_observers ActionDispatch::Reloader.to_prepare do ::Mongoid.instantiate_observers end end end end end end https://github.com/mongoid/mongoid/blob/3.0.0-stable/lib/mongoid/railtie.rb Mongoid
  61. module Haml module Rails class Railtie < ::Rails::Railtie config.before_initialize do

    Haml.init_rails(binding) Haml::Template.options[:format] = :html5 end end end end https://github.com/indirect/haml-rails/blob/v0.3.5/lib/haml-rails.rb Haml
  62. Generators

  63. simple_form lib generators simple_form install_generator.rb https://github.com/plataformatec/simple_form SimpleForm

  64. simple_form lib generators simple_form install_generator.rb Namespace https://github.com/plataformatec/simple_form SimpleForm

  65. simple_form lib generators simple_form install_generator.rb Namespace Generator https://github.com/plataformatec/simple_form SimpleForm

  66. module SimpleForm module Generators class InstallGenerator < Rails::Generators::Base desc "Copy

    SimpleForm default files" source_root File.expand_path('../templates', __FILE__) def copy_config directory 'config' end def copy_scaffold_template # ... end end end end https://github.com/plataformatec/simple_form/blob/v2.0.2/lib/generators/simple_form/install_generator.rb SimpleForm
  67. rails generate simple_form:install

  68. Convenções

  69. module MyGem class Railtie < ::Rails::Railtie generators do require "my_gem/generators"

    end end end
  70. Generators + Hooks

  71. module ActiveRecord class Railtie < Rails::Railtie config.app_generators.orm :active_record, :migration =>

    true, :timestamps => true end end https://github.com/rails/rails/tree/3-2-stable/activerecord/lib/active_record/railtie.rb Active Record
  72. module Rails module Mongoid class Railtie < Rails::Railtie def self.generator

    config.respond_to?(:app_generators) ? :app_generators : :generators end config.send(generator).orm :mongoid, migration: false end end end https://github.com/mongoid/mongoid/blob/3.0.0-stable/lib/mongoid/railtie.rb Mongoid
  73. module RSpec module Rails class Railtie < ::Rails::Railtie generators =

    config.respond_to?(:app_generators) ? config.app_generators : config.generators generators.integration_tool :rspec generators.test_framework :rspec end end end https://github.com/rspec/rspec-rails/blob/v2.11.0/lib/rspec-rails.rb RSpec
  74. module Responders class Railtie < ::Rails::Railtie if config.respond_to?(:app_generators) config.app_generators.scaffold_controller =

    :responders_controller else config.generators.scaffold_controller = :responders_controller end end end https://github.com/plataformatec/responders/blob/v0.9.2/lib/responders.rb Responders
  75. module Haml module Rails class Railtie < ::Rails::Railtie if ::Rails.version.to_f

    >= 3.1 config.app_generators.template_engine :haml else config.generators.template_engine :haml end end end end https://github.com/indirect/haml-rails/blob/v0.3.5/lib/haml-rails.rb Haml
  76. :assets => true :force_plural => false :helper => true :integration_tool

    => nil :javascripts => true :javascript_engine => :js :orm => false :performance_tool => nil :resource_controller => :controller :resource_route => true :scaffold_controller => :scaffold_controller :stylesheets => true :stylesheet_engine => :css :test_framework => false :template_engine => :erb https://github.com/rails/rails/blob/3-2-stable/railties/lib/rails/generators.rb
  77. Console

  78. module MyGem class Railtie < Rails::Railtie console do puts "Hello

    console!" end end end
  79. module ActiveRecord class Railtie < Rails::Railtie console do |app| if

    app.sandbox? require "active_record/railties/console_sandbox" end ActiveRecord::Base.logger = Logger.new(STDERR) end end end https://github.com/rails/rails/tree/3-2-stable/activerecord/lib/active_record/railtie.rb Active Record
  80. module PryRails class Railtie < Rails::Railtie console do # ...

    código para carregar o Pry end end end https://github.com/rweng/pry-rails/blob/master/lib/pry-rails/railtie.rb Pry Rails
  81. Rails 4 SPOILER

  82. RAILS 4 https://github.com/rails/rails/commit/951b582

  83. module PryRails class Railtie < Rails::Railtie console do if Rails::VERSION::MAJOR

    == 4 Rails.application.config.console = Pry end end end end https://github.com/rweng/pry-rails/blob/master/lib/pry-rails/railtie.rb Pry Rails
  84. Rake Tasks

  85. module RSpec module Rails class Railtie < ::Rails::Railtie rake_tasks do

    load "rspec/rails/tasks/rspec.rake" end end end end https://github.com/rspec/rspec-rails/blob/v2.11.0/lib/rspec-rails.rb RSpec
  86. module ActiveRecord class Railtie < Rails::Railtie rake_tasks do load "active_record/railties/databases.rake"

    end end end https://github.com/rails/rails/tree/3-2-stable/activerecord/lib/active_record/railtie.rb Active Record
  87. module Rails module Mongoid class Railtie < Rails::Railtie rake_tasks do

    load "mongoid/railties/database.rake" end end end end https://github.com/mongoid/mongoid/blob/3.0.0-stable/lib/mongoid/railtie.rb Mongoid
  88. Framework Loading

  89. module MyGem module SimpleFormExtensions def special_input(*) # ... end end

    end SimpleForm::FormBuilder.send( :include, MyGem::SimpleFormExtensions)
  90. module MyGem module SimpleFormExtensions def special_input(*) # ... end end

    end SimpleForm::FormBuilder.send( :include, MyGem::SimpleFormExtensions)
  91. module SimpleForm class FormBuilder end end ActiveSupport.run_load_hooks( :simple_form, SimpleForm::FormBuilder)

  92. module MyGem module SimpleFormExtensions def special_input(*) # ... end end

    end ActiveSupport.on_load(:simple_form) do include MyGem::SimpleFormExtensions end
  93. module ActiveRecord class Base end end ActiveSupport.run_load_hooks( :active_record, ActiveRecord::Base) https://github.com/rails/rails/blob/3-2-stable/activerecord/lib/active_record/base.rb

    Active Record
  94. module ActiveRecord class Railtie < Rails::Railtie initializer "active_record.initialize_timezone" do ActiveSupport.on_load(:active_record)

    do self.time_zone_aware_attributes = true self.default_timezone = :utc end end end end https://github.com/rails/rails/tree/3-2-stable/activerecord/lib/active_record/railtie.rb Active Record
  95. module MyGem module ActiveRecordExtensions end end ActiveSupport.on_load(:active_record) do include MyGem::ActiveRecordExtensions

    end
  96. ActiveSupport.on_load(:active_record) do include MyGem::ActiveRecordExtensions end ActiveSupport.on_load(:action_controller) do include MyGem::ActionControllerExtensions end

  97. Criar uma Railtie?

  98. module MyGem class Railtie < Rails::Railtie end end

  99. Você nem sempre precisa de uma Railtie!

  100. Initializers Railtie: quando?

  101. rake tasks Railtie: quando?

  102. Expor configs de sua gem Railtie: quando?

  103. Extensões para o console Railtie: quando?

  104. Generators em outro diretório Railtie: quando?

  105. Alterar um generator default Railtie: quando?

  106. Rails:: Engine

  107. Engine < Railtie

  108. Paths + Autoload

  109. app/ * assets controllers helpers mailers models views

  110. https://github.com/plataformatec/devise/tree/v2.1.2/app

  111. config/ environments/ #{Rails.env}.rb initializers/*.rb locales/*.{rb,yml} routes.rb

  112. https://github.com/plataformatec/devise/tree/v2.1.2/config

  113. lib/ assets/* tasks/*.rake vendor/ assets/*

  114. https://github.com/rails/jquery-rails/tree/v2.1.2/vendor/assets/javascripts

  115. module MyGem class Railtie < ::Rails::Engine # Você pode alterar

    os paths padrão. paths.app.controllers << "lib/controllers" end end
  116. Criar uma Engine?

  117. module MyGem class Railtie < ::Rails::Engine end end

  118. module Jquery module Rails class Engine < ::Rails::Engine end end

    end https://github.com/rails/jquery-rails/blob/v2.1.2/lib/jquery/rails/engine.rb Jquery Rails
  119. module Devise class Engine < ::Rails::Engine config.devise = Devise #

    Force routes to be loaded if we are doing any # eager load. config.before_eager_load { |app| app.reload_routes! } initializer "devise.url_helpers" do Devise.include_helpers(Devise::Controllers) end initializer "devise.omniauth" do |app| # ... end # ... end end https://github.com/plataformatec/devise/blob/v2.1.2/lib/devise/rails.rb Devise
  120. Quando eu preciso de uma Engine?

  121. Rotas Railtie: quando?

  122. Models Railtie: quando?

  123. Controllers Railtie: quando?

  124. Views Railtie: quando?

  125. app/* Railtie: quando?

  126. config/* Railtie: quando?

  127. Rails:: Plugin

  128. Plugin < Engine

  129. rails plugin install

  130. vendor/plugins

  131. init.rb

  132. Criar uma Plugin?

  133. Você não cria :)

  134. module Rails class Plugin < Engine def self.inherited(base) raise "You

    cannot inherit from Rails::Plugin" end end end https://github.com/rails/rails/blob/3-2-stable/railties/lib/rails/plugin.rb
  135. module Rails class Plugin < Engine def self.inherited(base) raise "You

    cannot inherit from Rails::Plugin" end end end https://github.com/rails/rails/blob/3-2-stable/railties/lib/rails/plugin.rb def self.inherited(base) raise "You cannot inherit from Rails::Plugin" end
  136. Lembre-se: interno ao Rails :)

  137. Quando eu preciso de um Plugin?

  138. Você não precisa (não mais :)

  139. Rails 4 SPOILER

  140. RAILS 4 https://github.com/rails/rails/commit/dad7fdc

  141. gems <3

  142. Rails:: Application

  143. Application < Engine

  144. Start!

  145. require config/boot.rb Rails boot

  146. require railties + engines Rails boot

  147. Define Rails.application Rails boot

  148. Run before_configuration Rails boot

  149. Load config/environment/ENV.rb Rails boot

  150. Run before_initialize Rails boot

  151. Initialize railties Rails boot

  152. Configure railties Rails boot

  153. Run railties#initializers Rails boot

  154. Build middleware Rails boot

  155. Run to_prepare Rails boot

  156. Run before_eager_load Rails boot

  157. Run after_initialize Rails boot

  158. Booted!

  159. Criar uma Application?

  160. rails new my_app

  161. module MyApp class Application < Rails::Application end end

  162. >> require 'rails/all' => true >> class MyApp < Rails::Application;

    end => nil >> Rails.application => #<MyApp:0x007f99b98c8728 @initialized=false ... > >> class OtherApp < Rails::Application; end RuntimeError: You cannot have more than one Rails::Application
  163. Single Responsibility Principle

  164. Win!

  165. Criando uma gem

  166. Bundler

  167. $ bundle gem rsonrails create rsonrails/Gemfile create rsonrails/Rakefile create rsonrails/LICENSE.txt

    create rsonrails/README.md create rsonrails/.gitignore create rsonrails/rsonrails.gemspec create rsonrails/lib/rsonrails.rb create rsonrails/lib/rsonrails/version.rb Initializating git repo in /Users/carlos/rsonrails bundle gem
  168. Copyright (c) 2012 Carlos Antonio da Silva MIT License Permission

    is hereby granted, free of charge, to any person obtaining... License
  169. # Rsonrails TODO: Write a gem description ## Installation Add

    this line to your application's Gemfile: gem 'rsonrails' ... ## Usage ... ## Contributing ... Readme
  170. source 'https://rubygems.org' # Specify your gem's dependencies in rsonrails.gemspec gemspec

    Gemfile
  171. # -*- encoding: utf-8 -*- lib = File.expand_path('../lib', __FILE__) $LOAD_PATH.unshift(lib)

    unless $LOAD_PATH.include?(lib) require 'rsonrails/version' Gem::Specification.new do |gem| gem.name = "rsonrails" gem.version = Rsonrails::VERSION gem.authors = ["Carlos Antonio da Silva"] gem.email = ["carlosantoniodasilva@gmail.com"] gem.description = %q{TODO: Write a gem description} gem.summary = %q{TODO: Write a gem summary} gem.homepage = "" gem.files = `git ls-files`.split($/) gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) } gem.test_files = gem.files.grep(%r{^(test|spec|features)/}) gem.require_paths = ["lib"] end rsonrails.gemspec
  172. require "rsonrails/version" module Rsonrails # Your code goes here... end

    lib/rsonrails.rb
  173. module Rsonrails VERSION = "0.0.1" end lib/rsonrails/version.rb

  174. Railtie?

  175. module Rsonrails class Railtie < Rails::Railtie # config.rsonrails = ActiveSupport::OrderedOptions.new

    # rake_tasks {} # config.to_prepare {} # initializer {} end end lib/rsonrails.rb
  176. module Rsonrails class Railtie < Rails::Railtie # config.rsonrails = ActiveSupport::OrderedOptions.new

    # rake_tasks {} # config.to_prepare {} # initializer {} end end require "rsonrails/version" require "rsonrails/railtie" module Rsonrails # Your code goes here... end lib/rsonrails/railtie.rb lib/rsonrails.rb
  177. ! Rails?

  178. require "rsonrails/version" if defined?(Rails) require "rsonrails/railtie" end module Rsonrails #

    Your code goes here... end lib/rsonrails.rb
  179. require "bundler/gem_tasks" Rakefile

  180. $ rake -T rake build # Build rsonrails-0.0.1.gem into the

    pkg directory rake install # Build and install rsonrails-0.0.1.gem into system gems rake release # Create tag v0.0.1 and build and push rsonrails-0.0.1.gem to Rubygems rake tasks
  181. Bundler

  182. Bundler <3 <3 <3

  183. None
  184. Railtie Engine Application

  185. None
  186. plataformatec/ simple_form

  187. plataformatec/ responders

  188. plataformatec/ devise

  189. rails/rails/ **/*railtie.rb

  190. http://pragprog.com/book/jvrails/crafting-rails-applications

  191. WITH GREAT MOUSTACHE COMES GREAT RESPONSIBILITY

  192. Estamos contratando! plataformatec.com.br

  193. None
  194. INTEGRANDO GEMS COM O RAILS @cantoniodasilva Obrigado!