Como posso chamar os métodos controller / view helper no console do Ruby on Rails?

442

Quando carrego script/console, às vezes quero jogar com a saída de um controlador ou de um método auxiliar de exibição.

Existem maneiras de:

  • simular uma solicitação?
  • chamar métodos de uma instância do controlador no referido pedido?
  • métodos auxiliares de teste, por meio da instância do controlador ou de outra maneira?
kch
fonte

Respostas:

479

Para chamar auxiliares, use o helperobjeto:

$ ./script/console
>> helper.number_to_currency('123.45')
=> "R$ 123,45"

Se você quiser usar um auxiliar que não está incluído por padrão (por exemplo, porque você removido helper :alla partir ApplicationController), basta incluir o ajudante.

>> include BogusHelper
>> helper.bogus
=> "bogus output"

Quanto a lidar com controladores , cito a resposta de Nick :

> app.get '/posts/1'
> response = app.response
# you now have a rails response object much like the integration tests

> response.body            # get you the HTML
> response.cookies         # hash of the cookies

# etc, etc
kch
fonte
4
Observo que não consigo executar mais de um app.get(ocorre um erro de thread). Existe uma maneira de liberar o sistema e executar mais ganhos?
JellicleCat
2
Observe no Rails 3.2 que isso não funciona. Eu precisava ligar url_fordo console. Para fazer isso eu fizapp.url_for(...)
Raphael
1
Para NoMethodError: undefined method `protect_against_forgery?' for nil:NilClassdefinir uma função chamada protect_against_forgery?no console que os retornosfalse
Sida Zhou
como faço para definir o usuário conectado no momento?
1
@RudolfOlah Parece que se você estiver usando um dispositivo (ou diretor), poderá fazê-lo ActionDispatch::Integration::Session.include(Warden::Test::Helpers); Warden.test_mode! ; app.login_as(User.find(1), scope: :user).
Eloyesp
148

Uma maneira fácil de chamar uma ação do controlador a partir de um script / console e exibir / manipular o objeto de resposta é:

> app.get '/posts/1'
> response = app.response
# You now have a Ruby on Rails response object much like the integration tests

> response.body            # Get you the HTML
> response.cookies         # Hash of the cookies

# etc., etc.

O objeto do aplicativo é uma instância do ActionController :: Integration :: Session

Isso funciona para mim usando o Ruby on Rails 2.1 e 2.3 e não tentei versões anteriores.

usuario
fonte
2
Um link para a documentação oficial sobre o objeto do aplicativo seria bom.
RajaRaviVarma
É uma instância da classe ActionController :: Integration :: Session. Atualizei a resposta para incluir isso.
Nick
Boa ideia. Eu não tinha pensado nisso.
Marnen Laibow-Koser 27/09/12
5
Como autenticar o console para verificar os controladores que exigem autenticação?
Mild Fuzz
7
Você deve poder postar na sua página de login, algo como: app.post '/ session / new', {: nome do usuário => "foo",: senha => "pass"}. E, em seguida, continue usando a mesma variável "app" para obter páginas depois disso.
Nick
108

Se você precisar testar no console (testado no Ruby on Rails 3.1 e 4.1):

Ações do controlador de chamada:

app.get '/'
   app.response
   app.response.headers  # => { "Content-Type"=>"text/html", ... }
   app.response.body     # => "<!DOCTYPE html>\n<html>\n\n<head>\n..."

Métodos ApplicationController:

foo = ActionController::Base::ApplicationController.new
foo.public_methods(true||false).sort
foo.some_method

Auxiliares de rota:

app.myresource_path     # => "/myresource"
app.myresource_url      # => "http://www.example.com/myresource"

Exibir auxiliares:

foo = ActionView::Base.new

foo.javascript_include_tag 'myscript' #=> "<script src=\"/javascripts/myscript.js\"></script>"

helper.link_to "foo", "bar" #=> "<a href=\"bar\">foo</a>"

ActionController::Base.helpers.image_tag('logo.png')  #=> "<img alt=\"Logo\" src=\"/images/logo.png\" />"

Render:

views = Rails::Application::Configuration.new(Rails.root).paths["app/views"]
views_helper = ActionView::Base.new views
views_helper.render 'myview/mytemplate'
views_helper.render file: 'myview/_mypartial', locals: {my_var: "display:block;"}
views_helper.assets_prefix  #=> '/assets'

Métodos do ActiveSupport:

require 'active_support/all'
1.week.ago
=> 2013-08-31 10:07:26 -0300
a = {'a'=>123}
a.symbolize_keys
=> {:a=>123}

Módulos Lib:

> require 'my_utils'
 => true
> include MyUtils
 => Object
> MyUtils.say "hi"
evaluate: hi
 => true
Fernando Fabreti
fonte
1
Isso ajuda quando você está escrevendo scripts ruby ​​independentes que serão executados usando o rails runner e eles precisam chamar métodos no controlador de aplicativo. Obrigado
CodeExpress 15/03/2015
@ CodeExpress Isso nunca deve acontecer. Em vez disso, coloque os métodos em um objeto de serviço e chame o serviço do ApplicationController e do seu script.
Marnen Laibow-Koser
77

Aqui está uma maneira de fazer isso através do console:

>> foo = ActionView::Base.new
=> #<ActionView::Base:0x2aaab0ac2af8 @assigns_added=nil, @assigns={}, @helpers=#<ActionView::Base::ProxyModule:0x2aaab0ac2a58>, @controller=nil, @view_paths=[]>

>> foo.extend YourHelperModule
=> #<ActionView::Base:0x2aaab0ac2af8 @assigns_added=nil, @assigns={}, @helpers=#<ActionView::Base::ProxyModule:0x2aaab0ac2a58>, @controller=nil, @view_paths=[]>

>> foo.your_helper_method(args)
=> "<html>created by your helper</html>"

Criar uma nova instância de ActionView::Basefornece acesso aos métodos de exibição normais que seu ajudante provavelmente usa. Em seguida, estender YourHelperModulecombina seus métodos em seu objeto, permitindo visualizar os valores de retorno.

Gordon Wilson
fonte
15

Se o método for o POSTmétodo, então:

app.post 'controller/action?parameter1=value1&parameter2=value2'

(Aqui os parâmetros serão de acordo com a sua aplicabilidade.)

Caso contrário, se for o GETmétodo, então:

app.get 'controller/action'
Swapnil Chincholkar
fonte
1
E para encontrar caminhos que você quer, app.methods.grep(/_path/):)
Dorian
E não é sempre controler/action, depende de suas rotas, por exemplo, poderia ser /users/alle mapear para Api::UsersController#index:)
Dorian
@Dorian Or rake routes. :)
Marnen Laibow-Koser
14

Outra maneira de fazer isso é usar o depurador Ruby on Rails. Há um guia do Ruby on Rails sobre depuração em http://guides.rubyonrails.org/debugging_rails_applications.html

Basicamente, inicie o servidor com a opção -u:

./script/server -u

E, em seguida, insira um ponto de interrupção no seu script, onde você gostaria de ter acesso aos controladores, ajudantes etc.

class EventsController < ApplicationController
  def index
    debugger
  end
end

E quando você faz uma solicitação e atinge essa parte do código, o console do servidor retornará um prompt onde você poderá fazer solicitações, visualizar objetos etc. em um prompt de comando. Quando terminar, basta digitar 'cont' para continuar a execução. Também existem opções para depuração estendida, mas isso deve pelo menos ajudá-lo a começar.

Dan McNevin
fonte
3
> => Aviso: a opção depurador é ignorada desde o Ruby 2.0 e será removida em versões futuras.
estrela brilhante
13

Aqui está como fazer uma solicitação POST autenticada, usando a refinaria como exemplo:

# Start Rails console
rails console
# Get the login form
app.get '/community_members/sign_in'
# View the session
app.session.to_hash
# Copy the CSRF token "_csrf_token" and place it in the login request.
# Log in from the console to create a session
app.post '/community_members/login', {"authenticity_token"=>"gT7G17RNFaWUDLC6PJGapwHk/OEyYfI1V8yrlg0lHpM=",  "refinery_user[login]"=>'chloe', 'refinery_user[password]'=>'test'}
# View the session to verify CSRF token is the same
app.session.to_hash
# Copy the CSRF token "_csrf_token" and place it in the request. It's best to edit this in Notepad++
app.post '/refinery/blog/posts', {"authenticity_token"=>"gT7G17RNFaWUDLC6PJGapwHk/OEyYfI1V8yrlg0lHpM=", "switch_locale"=>"en", "post"=>{"title"=>"Test", "homepage"=>"0", "featured"=>"0", "magazine"=>"0", "refinery_category_ids"=>["1282"], "body"=>"Tests do a body good.", "custom_teaser"=>"", "draft"=>"0", "tag_list"=>"", "published_at(1i)"=>"2014", "published_at(2i)"=>"5", "published_at(3i)"=>"27", "published_at(4i)"=>"21", "published_at(5i)"=>"20", "custom_url"=>"", "source_url_title"=>"", "source_url"=>"", "user_id"=>"56", "browser_title"=>"", "meta_description"=>""}, "continue_editing"=>"false", "locale"=>:en}

Você também pode achar útil se você receber um erro:

app.cookies.to_hash
app.flash.to_hash
app.response # long, raw, HTML
Chloe
fonte
2
NameError: undefined local variable or method app for main:Object
Kamil Lelonek
você também precisa desativar forgery_protectionApplicationController.allow_forgery_protection = false
William Herry
Uau, isso é provavelmente mais fácil. O que escrevi é com proteção contra falsificações. Você não precisa desativá-lo, mas tenho certeza que é mais conveniente!
Chloe
12

Você pode acessar seus métodos no console do Ruby on Rails da seguinte maneira:

controller.method_name
helper.method_name
Jyothu
fonte
7

As respostas anteriores estão chamando ajudantes, mas o seguinte ajudará na chamada de métodos do controlador. Eu usei isso no Ruby on Rails 2.3.2.

Primeiro adicione o seguinte código ao seu arquivo .irbrc (que pode estar no seu diretório pessoal)

class Object
   def request(options = {})
     url=app.url_for(options)
     app.get(url)
     puts app.html_document.root.to_s
  end
end

Em seguida, no console do Ruby on Rails, você pode digitar algo como ...

request(:controller => :show, :action => :show_frontpage)

... e o HTML será despejado no console.

David Knight
fonte
3

Dentro de qualquer ação ou exibição do controlador, você pode chamar o console chamando o método do console .

Por exemplo, em um controlador:

class PostsController < ApplicationController
  def new
    console
    @post = Post.new
  end
end

Ou em uma visão:

<% console %>

<h2>New Post</h2>

Isso renderizará um console dentro da sua visualização. Você não precisa se preocupar com o local da chamada do console; ele não será renderizado no local da invocação, mas próximo ao seu conteúdo HTML.

Veja: http://guides.rubyonrails.org/debugging_rails_applications.html

Gayan Weerakutti
fonte
3

Para controladores, você pode instanciar um objeto de controlador no console do Ruby on Rails.

Por exemplo,

class CustomPagesController < ApplicationController

  def index
    @customs = CustomPage.all
  end

  def get_number
    puts "Got the Number"
  end

  protected

  def get_private_number
    puts 'Got private Number'
  end

end

custom = CustomPagesController.new
2.1.5 :011 > custom = CustomPagesController.new
 => #<CustomPagesController:0xb594f77c @_action_has_layout=true, @_routes=nil, @_headers={"Content-Type"=>"text/html"}, @_status=200, @_request=nil, @_response=nil>
2.1.5 :014 > custom.get_number
Got the Number
 => nil

# For calling private or protected methods,
2.1.5 :048 > custom.send(:get_private_number)
Got private Number
 => nil
Dyaniyal Wilson
fonte
Funciona! Mas como posso atualizar variáveis ​​de ação. Ex: def show response = @user.contributions end Como faço para substituir a @uservariável?
Fábio Araújo
2

Uma abordagem possível para o teste do método Helper no console do Ruby on Rails é:

Struct.new(:t).extend(YourHelper).your_method(*arg)

E para recarregar faça:

reload!; Struct.new(:t).extend(YourHelper).your_method(*arg)
Dino Reic
fonte
1

Se você adicionou seu próprio auxiliar e deseja que seus métodos estejam disponíveis no console, faça:

  1. No console, execute include YourHelperName
  2. Seus métodos auxiliares agora estão disponíveis no console e use-os chamando method_name(args)no console.

Exemplo: digamos que você tenha o MyHelper (com um método my_method) em 'app / helpers / my_helper.rb` e, no console, faça:

  1. include MyHelper
  2. my_helper.my_method
Desenvolvedor Marius Žilėnas
fonte