Wie kann ich Controller- / View-Hilfsmethoden von der Konsole in Ruby on Rails aus aufrufen?

442

Wenn ich lade script/console, möchte ich manchmal mit der Ausgabe eines Controllers oder einer View-Helper-Methode spielen.

Gibt es Möglichkeiten, um:

  • Anfrage simulieren?
  • Methoden von einer Controller-Instanz auf diese Anfrage aufrufen?
  • Hilfsmethoden testen, entweder über die Controller-Instanz oder auf andere Weise?
kch
quelle

Antworten:

479

Verwenden Sie das helperObjekt , um Helfer anzurufen :

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

Wenn Sie einen Helfer verwenden möchten, die standardmäßig enthalten ist nicht (weil Sie entfernt helper :allaus ApplicationController), sind nur die Helfer.

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

In Bezug auf den Umgang mit Controllern zitiere ich Nicks Antwort:

> 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
quelle
4
Ich beobachte, dass ich nicht mehr als einen ausführen kann app.get(ein Thread-Fehler tritt auf). Gibt es eine Möglichkeit, das System zu spülen und mehr Gets auszuführen?
JellicleCat
2
Beachten Sie in Rails 3.2, dass dies nicht funktioniert. Ich musste url_forvon der Konsole aus anrufen . Um dies zu tun, tat ichapp.url_for(...)
Raphael
1
Zum NoMethodError: undefined method `protect_against_forgery?' for nil:NilClassDefinieren einer Funktion, die protect_against_forgery?in der Konsole aufgerufen wird, die zurückgibtfalse
Sida Zhou
Wie stelle ich den aktuell angemeldeten Benutzer ein?
1
@ RudolfOlah Es scheint, dass Sie es tun können, wenn Sie ein Gerät (oder einen Aufseher) verwenden ActionDispatch::Integration::Session.include(Warden::Test::Helpers); Warden.test_mode! ; app.login_as(User.find(1), scope: :user).
Eloyesp
148

Eine einfache Möglichkeit, eine Controller-Aktion über ein Skript / eine Konsole aufzurufen und das Antwortobjekt anzuzeigen / zu bearbeiten, ist:

> 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.

Das App-Objekt ist eine Instanz von ActionController :: Integration :: Session

Dies funktioniert bei Verwendung von Ruby on Rails 2.1 und 2.3, und ich habe frühere Versionen nicht ausprobiert.

Nick
quelle
2
Ein Link zur offiziellen Dokumentation zum App-Objekt wäre gut.
RajaRaviVarma
Es ist eine Instanz der ActionController :: Integration :: Session-Klasse. Ich habe die Antwort aktualisiert, um dies aufzunehmen.
Nick
Großartige Idee. Daran hatte ich nicht gedacht.
Marnen Laibow-Koser
5
Wie kann ich die Konsole authentifizieren, um Controller zu überprüfen, für die eine Authentifizierung erforderlich ist?
Mild Fuzz
7
Sie sollten in der Lage sein, auf Ihrer Anmeldeseite Folgendes zu veröffentlichen: app.post '/ session / new', {: username => "foo" ,: password => "pass"}. Verwenden Sie dann weiterhin dieselbe "App" -Variable, um danach Seiten abzurufen.
Nick
108

Wenn Sie von der Konsole aus testen müssen (getestet auf Ruby on Rails 3.1 und 4.1):

Call Controller-Aktionen:

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

ApplicationController-Methoden:

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

Routenhelfer:

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

Helfer anzeigen:

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\" />"

Machen:

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'

ActiveSupport-Methoden:

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

Lib-Module:

> require 'my_utils'
 => true
> include MyUtils
 => Object
> MyUtils.say "hi"
evaluate: hi
 => true
Fernando Fabreti
quelle
1
Dies ist hilfreich, wenn Sie unabhängige Ruby-Skripte schreiben, die mit Rails Runner ausgeführt werden und Methoden im Application Controller aufrufen müssen. Vielen Dank
CodeExpress
@CodeExpress Das sollte niemals passieren. Fügen Sie stattdessen die Methoden in ein Dienstobjekt ein und rufen Sie den Dienst sowohl von ApplicationController als auch von Ihrem Skript aus auf.
Marnen Laibow-Koser
77

Hier ist eine Möglichkeit, dies über die Konsole zu tun:

>> 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>"

Durch das Erstellen einer neuen Instanz von erhalten ActionView::BaseSie Zugriff auf die normalen Ansichtsmethoden, die Ihr Helfer wahrscheinlich verwendet. Durch das Erweitern werden YourHelperModuledie Methoden in Ihr Objekt gemischt, sodass Sie deren Rückgabewerte anzeigen können.

Gordon Wilson
quelle
15

Wenn die Methode die Methode ist POST, dann:

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

(Hier richten sich die Parameter nach Ihrer Anwendbarkeit.)

Sonst, wenn es die GETMethode ist, dann:

app.get 'controller/action'
Swapnil Chincholkar
quelle
1
Und um Wege zu finden, die Sie wollen, app.methods.grep(/_path/):)
Dorian
Und es ist nicht immer controler/action, hängt von Ihren Routen ab, zB könnte sein /users/allund Karte zu Api::UsersController#index:)
Dorian
@ Dorian Or rake routes. En :)
Marnen Laibow-Koser
14

Eine andere Möglichkeit, dies zu tun, ist die Verwendung des Ruby on Rails-Debuggers. Unter http://guides.rubyonrails.org/debugging_rails_applications.html finden Sie eine Ruby on Rails-Anleitung zum Debuggen

Starten Sie den Server grundsätzlich mit der Option -u:

./script/server -u

Fügen Sie dann einen Haltepunkt in Ihr Skript ein, an dem Sie Zugriff auf die Controller, Helfer usw. haben möchten.

class EventsController < ApplicationController
  def index
    debugger
  end
end

Wenn Sie eine Anfrage stellen und diesen Teil im Code drücken, gibt die Serverkonsole eine Eingabeaufforderung zurück, in der Sie an einer Eingabeaufforderung Anforderungen stellen, Objekte anzeigen usw. können. Wenn Sie fertig sind, geben Sie einfach 'cont' ein, um die Ausführung fortzusetzen. Es gibt auch Optionen für erweitertes Debugging, aber dies sollte Ihnen zumindest den Einstieg erleichtern.

Dan McNevin
quelle
3
> => Hinweis: Die Debugger-Option wird seit Ruby 2.0 ignoriert und in zukünftigen Versionen entfernt.
heller Stern
13

So erstellen Sie eine authentifizierte POST-Anfrage am Beispiel der Raffinerie:

# 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}

Sie können diese auch nützlich finden, wenn Sie eine Fehlermeldung erhalten:

app.cookies.to_hash
app.flash.to_hash
app.response # long, raw, HTML
Chloe
quelle
2
NameError: undefined local variable or method app for main:Object
Kamil Lelonek
Sie müssen auch forgery_protection deaktivierenApplicationController.allow_forgery_protection = false
William Herry
Wow das ist wahrscheinlich einfacher. Was ich geschrieben habe, ist mit Fälschungsschutz. Sie müssen es nicht deaktivieren, aber ich bin sicher, es ist bequemer!
Chloe
12

Sie können in der Ruby on Rails-Konsole wie folgt auf Ihre Methoden zugreifen:

controller.method_name
helper.method_name
Jyothu
quelle
7

Die früheren Antworten rufen Helfer auf, aber die folgenden helfen beim Aufrufen von Controller-Methoden. Ich habe dies auf Ruby on Rails 2.3.2 verwendet.

Fügen Sie zuerst den folgenden Code zu Ihrer .irbrc-Datei hinzu (die sich in Ihrem Home-Verzeichnis befinden kann).

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

Dann können Sie in der Ruby on Rails-Konsole so etwas wie ...

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

... und der HTML-Code wird auf der Konsole gespeichert.

David Knight
quelle
3

Innerhalb jeder Controller - Aktion oder Ansicht, können Sie die Konsole durch den Aufruf der aufrufen Konsole Methode.

Zum Beispiel in einer Steuerung:

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

Oder in einer Ansicht:

<% console %>

<h2>New Post</h2>

Dadurch wird eine Konsole in Ihrer Ansicht gerendert. Sie müssen sich nicht um den Ort des Konsolenanrufs kümmern. Es wird nicht an der Stelle seines Aufrufs gerendert, sondern neben Ihrem HTML-Inhalt.

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

Gayan Weerakutti
quelle
3

Für Controller können Sie ein Controller-Objekt in der Ruby on Rails-Konsole instanziieren.

Zum Beispiel,

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
quelle
Es klappt! Aber wie kann ich Aktionsvariablen aktualisieren? Beispiel: def show response = @user.contributions end Wie überschreibe ich die @userVariable?
Fábio Araújo
2

Ein möglicher Ansatz für das Testen von Hilfsmethoden in der Ruby on Rails-Konsole ist:

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

Und zum Nachladen:

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

Wenn Sie einen eigenen Helfer hinzugefügt haben und dessen Methoden in der Konsole verfügbar sein sollen, gehen Sie wie folgt vor:

  1. In der Konsole ausführen include YourHelperName
  2. Ihre Hilfsmethoden sind jetzt in der Konsole verfügbar und werden method_name(args)in der Konsole aufgerufen.

Beispiel: Angenommen, Sie haben MyHelper (mit einer Methode my_method) in 'app / helpers / my_helper.rb', dann in der Konsole:

  1. include MyHelper
  2. my_helper.my_method
Entwickler Marius Žilėnas
quelle