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?
kch
źródło

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
kch
źródło
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.

Nacięcie
źródło
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
Fernando Fabreti
źródło
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.

Gordon Wilson
źródło
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'
Swapnil Chincholkar
źródło
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ąć.

Dan McNevin
źródło
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
Chloe
źródło
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
Jyothu
źródło
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.

David Knight
źródło
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

Gayan Weerakutti
źródło
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
Dyaniyal Wilson
źródło
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)
Dino Reic
źródło
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
Deweloper Marius Žilėnas
źródło