Jak mogę wywoływać metody kontrolera / pomocnika z konsoli w Ruby on Rails?


442

Kiedy ładuję script/console, czasami chcę grać z wyjściem kontrolera lub metodą pomocnika widoku.

Czy istnieją sposoby:

  • symulować zapytanie?
  • metody wywoływania z instancji kontrolera na to żądanie?
  • testować metody pomocnicze, albo poprzez wspomnianą instancję kontrolera, albo w inny sposób?

Odpowiedzi:


479

Aby wywołać pomocników, użyj helperobiektu:

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

Jeśli chcesz skorzystać z pomocnika, który nie jest włączone domyślnie (powiedzmy, ponieważ usunięto helper :allz ApplicationController), po prostu zawierać pomocnika.

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

Jeśli chodzi o kontrolery , cytuję odpowiedź Nicka :

> 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

4
Zauważam, że nie mogę wykonać więcej niż jednego app.get(pojawia się błąd wątku). Czy istnieje sposób, aby opróżnić system i wykonać więcej operacji pobierania?
JellicleCat

2
Uwaga w Railsach 3.2 to nie działa. Musiałem zadzwonić url_forz konsoli. Aby to zrobić, zrobiłemapp.url_for(...)
Raphael,

1
Aby NoMethodError: undefined method `protect_against_forgery?' for nil:NilClasszdefiniować funkcję wywoływaną protect_against_forgery?w konsoli, która zwracafalse
Sida Zhou,

jak ustawić aktualnie zalogowanego użytkownika?

1
@RudolfOlah Wygląda na to, że jeśli używasz urządzenia (lub naczelnika), możesz to zrobić ActionDispatch::Integration::Session.include(Warden::Test::Helpers); Warden.test_mode! ; app.login_as(User.find(1), scope: :user).
eloyesp

148

Prostym sposobem wywołania akcji kontrolera ze skryptu / konsoli i wyświetlenia / manipulowania obiektem odpowiedzi jest:

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

Obiekt aplikacji jest instancją ActionController :: Integration :: Session

Działa to dla mnie przy użyciu Ruby on Rails 2.1 i 2.3 i nie próbowałem wcześniejszych wersji.


2
Link do oficjalnej dokumentacji obiektu aplikacji byłby dobry.
RajaRaviVarma

Jest to instancja klasy ActionController :: Integration :: Session. Zaktualizowałem odpowiedź, aby ją uwzględnić.
Nick

Świetny pomysł. Nie myślałem o tym.
Marnen Laibow-Koser

5
Jak mogę uwierzytelnić konsolę, aby sprawdzić kontrolery wymagające uwierzytelnienia?
Łagodny Fuzz,

7
Powinieneś mieć możliwość publikowania postów na swojej stronie logowania, na przykład: app.post '/ session / new', {: nazwa użytkownika => „foo”,: hasło => „pass”}. A następnie nadal używaj tej samej zmiennej „app”, aby później uzyskać strony.
Nick

108

Jeśli chcesz przetestować z konsoli (testowane na Ruby on Rails 3.1 i 4.1):

Działania kontrolera połączeń:

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

Metody ApplicationController:

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

Pomocnicy trasy:

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

Wyświetl pomocników:

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

Renderowanie:

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'

Metody ActiveSupport:

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

Moduły Lib:

> require 'my_utils'
 => true
> include MyUtils
 => Object
> MyUtils.say "hi"
evaluate: hi
 => true

1
Pomaga to w pisaniu niezależnych skryptów ruby, które będą uruchamiane przy użyciu programu runner i muszą wywoływać metody w kontrolerze aplikacji. Dzięki
CodeExpress,

@CodeExpress To nigdy nie powinno się zdarzyć. Zamiast tego umieść metody w obiekcie usługi i wywołaj usługę zarówno z ApplicationController, jak i skryptu.
Marnen Laibow-Koser

77

Oto jeden ze sposobów, aby to zrobić za pomocą konsoli:

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

Utworzenie nowej instancji ActionView::Basedaje dostęp do normalnych metod widoku, z których prawdopodobnie korzysta Twój pomocnik. Następnie rozszerzenie YourHelperModulemiksuje swoje metody w obiekcie, umożliwiając przeglądanie ich zwracanych wartości.


15

Jeśli metoda jest POSTmetodą, to:

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

(Tutaj parametry będą zgodne z Twoim zastosowaniem).

W przeciwnym razie, jeśli jest to GETmetoda, to:

app.get 'controller/action'

1
I znaleźć ścieżki, które chcesz, app.methods.grep(/_path/):)
Dorian

I to nie zawsze controler/actionzależy od twoich tras, np. Może być /users/alli mapować do Api::UsersController#index:)
Dorian

@Dorian Or rake routes. :)
Marnen Laibow-Koser

14

Innym sposobem na to jest skorzystanie z debugera Ruby on Rails. Istnieje przewodnik Ruby on Rails na temat debugowania na stronie http://guides.rubyonrails.org/debugging_rails_applications.html

Zasadniczo uruchom serwer z opcją -u:

./script/server -u

A następnie wstaw punkt przerwania do skryptu, w którym chcesz mieć dostęp do kontrolerów, pomocników itp.

class EventsController < ApplicationController
  def index
    debugger
  end
end

Po złożeniu żądania i naciśnięciu tej części kodu konsola serwera zwróci monit, w którym można następnie wysyłać żądania, wyświetlać obiekty itp. Z wiersza polecenia. Po zakończeniu wpisz „cont”, aby kontynuować wykonywanie. Istnieją również opcje rozszerzonego debugowania, ale powinno to przynajmniej zacząć.


3
> => Uwaga: opcja debugowania jest ignorowana od Ruby 2.0 i zostanie usunięta w przyszłych wersjach.
jasna gwiazda

13

Oto jak wykonać uwierzytelnione żądanie POST na przykładzie Rafinerii:

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

Te mogą być również przydatne, jeśli pojawi się błąd:

app.cookies.to_hash
app.flash.to_hash
app.response # long, raw, HTML

2
NameError: undefined local variable or method app for main:Object
Kamil Lelonek

musisz także wyłączyć opcjęembry_protectionApplicationController.allow_forgery_protection = false
William Herry

Wow, to chyba łatwiejsze. To, co napisałem, dotyczy ochrony przed fałszowaniem. Nie musisz go wyłączać, ale jestem pewien, że jest to wygodniejsze!
Chloe

12

Możesz uzyskać dostęp do swoich metod w konsoli Ruby on Rails w następujący sposób:

controller.method_name
helper.method_name


7

Wcześniejsze odpowiedzi wywołują pomocników, ale poniższe pomogą w wywołaniu metod kontrolera. Użyłem tego na Ruby on Rails 2.3.2.

Najpierw dodaj następujący kod do pliku .irbrc (który może znajdować się w katalogu domowym)

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

Następnie w konsoli Ruby on Rails możesz wpisać coś takiego ...

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

... a HTML zostanie zrzucony do konsoli.


3

Wewnątrz dowolnej akcji lub widoku kontrolera można wywołać konsolę, wywołując metodę konsoli .

Na przykład w kontrolerze:

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

Lub w widoku:

<% console %>

<h2>New Post</h2>

Spowoduje to wyświetlenie konsoli w twoim widoku. Nie musisz dbać o lokalizację połączenia z konsolą; nie będzie renderowany w miejscu wywołania, ale obok treści HTML.

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


3

W przypadku kontrolerów możesz utworzyć obiekt kontrolera w konsoli Ruby on Rails.

Na przykład,

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

To działa! Ale jak mogę zaktualizować zmienne akcji. Przykład: def show response = @user.contributions end Jak zastąpić @userzmienną?
Fábio Araújo

2

Jednym z możliwych podejść do testowania metod pomocniczych w konsoli Ruby on Rails jest:

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

I do przeładowania wykonaj:

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

1

Jeśli dodałeś własnego pomocnika i chcesz, aby jego metody były dostępne w konsoli, wykonaj:

  1. W konsoli wykonaj include YourHelperName
  2. Metody pomocnicze są teraz dostępne w konsoli i używaj ich do wywoływania method_name(args)w konsoli.

Przykład: powiedz, że masz MyHelper (z metodą my_method) w 'app / helpers / my_helper.rb`, a następnie w konsoli wykonaj:

  1. include MyHelper
  2. my_helper.my_method
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.