Comment puis-je appeler des méthodes d'assistance de contrôleur / vue à partir de la console dans Ruby on Rails?

442

Lorsque je charge script/console, parfois je veux jouer avec la sortie d'un contrôleur ou d'une méthode d'aide à la vue.

Existe-t-il des moyens de:

  • simuler une demande?
  • appeler des méthodes à partir d'une instance de contrôleur sur ladite demande?
  • tester les méthodes d'aide, soit via ladite instance de contrôleur ou d'une autre manière?
kch
la source

Réponses:

479

Pour appeler des assistants, utilisez l' helperobjet:

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

Si vous souhaitez utiliser un assistant qui n'est pas inclus par défaut (par exemple, parce que vous avez supprimé helper :allde ApplicationController), incluez simplement l'assistant.

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

En ce qui concerne les contrôleurs , je cite la réponse 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
la source
4
J'observe que je ne peux pas en exécuter plus d'un app.get(une erreur de thread s'ensuit). Existe-t-il un moyen de vider le système et d'exécuter plus de get?
JellicleCat
2
Remarque dans Rails 3.2, cela ne fonctionne pas. J'avais besoin d'appeler url_fordepuis la console. Pour ce faire, je l'ai faitapp.url_for(...)
Raphael
1
Pour NoMethodError: undefined method `protect_against_forgery?' for nil:NilClassdéfinir une fonction appelée protect_against_forgery?dans la console qui retournefalse
Sida Zhou
comment définir l'utilisateur actuellement connecté?
1
@RudolfOlah Il semble que si vous utilisez un appareil (ou un gardien), vous pouvez le faire avec ActionDispatch::Integration::Session.include(Warden::Test::Helpers); Warden.test_mode! ; app.login_as(User.find(1), scope: :user).
eloyesp
148

Un moyen simple d'appeler une action de contrôleur à partir d'un script / d'une console et de visualiser / manipuler l'objet de réponse est le suivant:

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

L'objet app est une instance de ActionController :: Integration :: Session

Cela fonctionne pour moi en utilisant Ruby on Rails 2.1 et 2.3, et je n'ai pas essayé les versions antérieures.

pseudo
la source
2
Un lien vers la documentation officielle sur l'objet de l'application serait bien.
RajaRaviVarma
Il s'agit d'une instance de la classe ActionController :: Integration :: Session. J'ai mis à jour la réponse pour l'inclure.
Nick
Bonne idée. Je n'y avais pas pensé.
Marnen Laibow-Koser
5
Comment puis-je authentifier la console, afin de pouvoir vérifier les contrôleurs qui nécessitent une authentification?
Mild Fuzz
7
Vous devriez pouvoir publier sur votre page de connexion, quelque chose comme: app.post '/ session / new', {: username => "foo",: password => "pass"}. Et puis continuez à utiliser la même variable "app" pour obtenir des pages après cela.
Nick
108

Si vous devez tester à partir de la console (testé sur Ruby on Rails 3.1 et 4.1):

Actions du contrôleur d'appel:

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

Méthodes ApplicationController:

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

Aides à l'itinéraire:

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

Afficher les assistants:

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

Rendre:

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éthodes ActiveSupport:

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

Modules Lib:

> require 'my_utils'
 => true
> include MyUtils
 => Object
> MyUtils.say "hi"
evaluate: hi
 => true
Fernando Fabreti
la source
1
Cela aide lorsque vous écrivez des scripts ruby ​​indépendants qui seront exécutés à l'aide de rails runner et qu'ils doivent appeler des méthodes dans le contrôleur d'application. Merci
CodeExpress
@CodeExpress Cela ne devrait jamais arriver. Au lieu de cela, placez les méthodes dans un objet de service et appelez le service à la fois depuis ApplicationController et votre script.
Marnen Laibow-Koser
77

Voici une façon de le faire via la 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>"

La création d'une nouvelle instance de ActionView::Basevous donne accès aux méthodes d'affichage normales que votre assistant utilise probablement. Ensuite, l'extension YourHelperModulemélange ses méthodes dans votre objet, vous permettant de visualiser leurs valeurs de retour.

Gordon Wilson
la source
15

Si la méthode est la POSTméthode, alors:

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

(Ici, les paramètres seront selon votre applicabilité.)

Sinon, si c'est la GETméthode, alors:

app.get 'controller/action'
Swapnil Chincholkar
la source
1
Et pour trouver les chemins que vous voulez, app.methods.grep(/_path/):)
Dorian
Et ce n'est pas toujours controler/action, cela dépend de vos itinéraires, par exemple pourrait être /users/allet mapper à Api::UsersController#index:)
Dorian
@Dorian Or rake routes. :)
Marnen Laibow-Koser
14

Une autre façon de procéder consiste à utiliser le débogueur Ruby on Rails. Il existe un guide Ruby on Rails sur le débogage à http://guides.rubyonrails.org/debugging_rails_applications.html

Fondamentalement, démarrez le serveur avec l'option -u:

./script/server -u

Et puis insérez un point d'arrêt dans votre script où vous souhaitez avoir accès aux contrôleurs, assistants, etc.

class EventsController < ApplicationController
  def index
    debugger
  end
end

Et lorsque vous effectuez une demande et appuyez sur cette partie dans le code, la console du serveur renvoie une invite où vous pouvez ensuite effectuer des demandes, afficher des objets, etc. à partir d'une invite de commande. Une fois terminé, tapez simplement «cont» pour continuer l'exécution. Il existe également des options de débogage étendu, mais cela devrait au moins vous aider à démarrer.

Dan McNevin
la source
3
> => Remarque: l'option de débogage est ignorée depuis Ruby 2.0 et elle sera supprimée dans les futures versions.
étoile brillante
13

Voici comment effectuer une demande POST authentifiée, en utilisant la raffinerie comme exemple:

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

Vous pouvez également les trouver utiles si vous obtenez une erreur:

app.cookies.to_hash
app.flash.to_hash
app.response # long, raw, HTML
Chloe
la source
2
NameError: undefined local variable or method app for main:Object
Kamil Lelonek
vous devez également désactiver forgery_protectionApplicationController.allow_forgery_protection = false
William Herry
Wow c'est probablement plus facile. Ce que j'ai écrit concerne la protection contre la contrefaçon. Vous n'avez pas besoin de le désactiver, mais je suis sûr que c'est plus pratique!
Chloé
12

Vous pouvez accéder à vos méthodes dans la console Ruby on Rails comme suit:

controller.method_name
helper.method_name
Jyothu
la source
7

Les réponses précédentes appellent des assistants, mais les suivantes vous aideront à appeler des méthodes de contrôleur. Je l'ai utilisé sur Ruby on Rails 2.3.2.

Ajoutez d'abord le code suivant à votre fichier .irbrc (qui peut être dans votre répertoire personnel)

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

Ensuite, dans la console Ruby on Rails, vous pouvez taper quelque chose comme ...

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

... et le HTML sera vidé sur la console.

David Knight
la source
3

Dans toute action ou vue de contrôleur, vous pouvez appeler la console en appelant la méthode console .

Par exemple, dans un contrôleur:

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

Ou en vue:

<% console %>

<h2>New Post</h2>

Cela rendra une console dans votre vue. Vous n'avez pas besoin de vous soucier de l'emplacement de l'appel de console; il ne sera pas rendu sur place lors de son invocation mais à côté de votre contenu HTML.

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

Gayan Weerakutti
la source
3

Pour les contrôleurs, vous pouvez instancier un objet contrôleur dans la console Ruby on Rails.

Par exemple,

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
la source
Ça marche! Mais comment puis-je mettre à jour les variables d'action. Ex: def show response = @user.contributions end Comment remplacer la @uservariable?
Fábio Araújo
2

Une approche possible pour les tests de méthode d'assistance dans la console Ruby on Rails est la suivante:

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

Et pour recharger, faites:

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

Si vous avez ajouté votre propre assistant et que vous souhaitez que ses méthodes soient disponibles dans la console, procédez comme suit:

  1. Dans la console, exécutez include YourHelperName
  2. Vos méthodes d'assistance sont maintenant disponibles dans la console et utilisez-les en appelant method_name(args)dans la console.

Exemple: disons que vous avez MyHelper (avec une méthode my_method) dans 'app / helpers / my_helper.rb`, puis dans la console faites:

  1. include MyHelper
  2. my_helper.my_method
Développeur Marius Žilėnas
la source