@evgeniy_trebin
Ruby on Rails developer

RSpec Как получить доступ к хелпер-методу контроллера или сделать заглушку для него в спеке для вьюхи?

Решил пропробовать гем decent_exposure. Он позволяет сократить код в CRUD контроллерах, но вместо переменных @article и @articles он создает хелпер-методы с соответствующими названиями. Но не пойму, как получить доступ к таким методам во вьюхе или же создать заглушку для них
Rspec 3.4, Rails 4.2.5

Account::ArticlesController
class Account::ArticlesController < Account::BaseController
  expose(:articles) { current_user.articles }
  expose(:article, attributes: :article_params)

  # POST /account/articles
  # POST /account/articles.json
  def create
    respond_to do |format|
      if article.save
        format.html { redirect_to account_article_url(article), notice: 'Article was successfully created.' }
        format.json { render :show, status: :created, location: account_article_url(article) }
      else
        format.html { render :new }
        format.json { render json: article.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /account/articles/1
  # PATCH/PUT /account/articles/1.json
  def update
    respond_to do |format|
      if article.update(article_params)
        format.html { redirect_to account_article_url(article), notice: 'Article was successfully updated.' }
        format.json { render :show, status: :ok, location: account_article_url(article) }
      else
        format.html { render :edit }
        format.json { render json: article.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /account/articles/1
  # DELETE /account/articles/1.json
  def destroy
    respond_to do |format|
      if article.destroy
        format.html { redirect_to account_articles_url, notice: 'Article was successfully destroyed.' }
        format.json { head :no_content }
      else
        format.html { redirect_to account_articles_url, notice: 'Article was not destroyed.' }
        format.json { render json: article.errors, status: :unprocessable_entity }
      end
    end
  end

  private

  def article_params
    params.require(:article).permit(:title, :announce, :content, :is_published, :published_at)
  end

end


вьюха экшена new
= form_for [:account, article], html: { class: "form-horizontal", role: "form" } do |f|
  -if article.errors.any?
    .alert.alert-danger.alert-dismissable{role: "alert"}
      %button.close{type: "button", data: {dismiss: "alert"} }
        %span{aria: {hidden: "true"} } &times;
        %span.sr-only Close
      %h4= "#{pluralize(article.errors.count, "error")} prohibited this article from being saved:"

      %ul
        - article.errors.full_messages.each do |msg|
          %li= msg

  .form-group
    .col-sm-offset-2.col-sm-10
      = f.submit class: 'btn btn-primary'


spec для вьюхи new
require 'rails_helper'

RSpec.describe 'account/articles/new', type: :view do

  before do
    allow(view).to receive(:article).and_return(build(:article))
  end

  it 'renders new article form' do
    render
    expect(rendered).to match %Q{form[action=#{account_articles_path}][method=post]}
  end
end


Ошибка
account/articles/new renders new article form
     Failure/Error: allow(view).to receive(:article).and_return(build(:article))


Если это убрать
allow(view).to receive(:article).and_return(build(:article))

То соответственно метод не определен
Failure/Error: = form_for [:account, article], html: { class: "form-horizontal", role: "form" } do |f|
     
     ActionView::Template::Error:
       undefined local variable or method `article' for #<#<Class:0x007fbb32b4ad30>:0x007fbb35c846a8>
  • Вопрос задан
  • 307 просмотров
Решения вопроса 1
@evgeniy_trebin Автор вопроса
Ruby on Rails developer
require 'rails_helper'

RSpec.describe 'account/articles/new', type: :view do

  it 'renders new article form' do
    stub_article { Article.new }
    render
    expect(rendered).to match(%r{form.+id="new_article".+action=\"#{account_articles_path}".+accept-charset=\"UTF-8\".+method=\"post\"})
  end

  def stub_article(&block)
    controller.singleton_class.class_exec(block) do
      helper_method :article
      define_method :article do
        block.call
      end
    end
  end

end


или более простой способ
require 'rails_helper'

RSpec.describe 'account/articles/new', type: :view do

  it 'renders new article form' do
    def view.article
      Article.new
    end
    render
    expect(rendered).to match %r{form.+id="new_article".+action=\"#{account_articles_path}".+accept-charset=\"UTF-8\".+method=\"post\"}
  end

end
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы