Giter Club home page Giter Club logo

fortitude's Issues

Missing fields_for helper, and some forms weirdness

It should be possible to do

form_for :test_form do |f|
  f.text_field "hello"
  f.fields_for :inner_thing do |inner|
    inner.text_field "greets"
  end
end

But fields_for is not a helper defined on form_for helper.

I added fields_for to the output_yielded_methods, which fixed it for my example above, generting the correct HTML:

<form accept-charset="UTF-8" action="/test_form" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /><input name="authenticity_token" type="hidden" value="j4Dax68aX/t7ajwBlpTTjeMT5MAaZjrNVYfE/yTW9ts=" /></div><input id="test_form_hello" name="test_form[hello]" size="30" type="text" /><input id="test_form_inner_thing_greets" name="test_form[inner_thing][greets]" size="30" type="text" /></form>

But, if I add an additional tag within the fields_for block, inner.text_field "greets" is no longer output.

form_for :test_form do |f|
  f.text_field "hello"
  f.fields_for :inner_thing do |inner|
    inner.text_field "greets"
    div "hello"
  end
end

Outputs the HTML, (notice the div tag is there, but not the input)

<form accept-charset="UTF-8" action="/test_form" method="post"><div style="margin:0;padding:0;display:inline"><input name="utf8" type="hidden" value="&#x2713;" /><input name="authenticity_token" type="hidden" value="j4Dax68aX/t7ajwBlpTTjeMT5MAaZjrNVYfE/yTW9ts=" /></div><input id="test_form_hello" name="test_form[hello]" size="30" type="text" /><div>hello</div></form>

static with varying

It would be cool if you could specify a list of needs that static caching could vary on. For example we want to cache some widgets but we also render them in different locales, so it would be nice to say something like:

static :html_content, varies: [:locale]

or something similar. Then for each value of locale that the widget renders from would use a different cache

Regression: automatic inclusion of Rails helpers breaks implicit route arguments

So I've actually looked for where this is documented in the Rails docs and can't find it, but given a route like this:

screen shot 2016-10-18 at 2 54 53 pm

And if you have instance variables for @site and @project, you can call the route explicitly:

project_admin_responses_path(@site.id, @project.id)

Or you can leave out the arguments, and Rails will implicitly pass your instance variables to the route helper:

project_admin_responses_path

However, the change in d7eeec4 (which I don't quite understand in the first place) breaks this second syntax:

screen shot 2016-10-18 at 2 56 15 pm

I think I understand why, but I'm wondering if this would be considered a regression, and if this is OK. I find it weird that you had to specify default_url_options in d7eeec4#diff-c039a5faaa76d9264a41ffc542ef3a82R87, since Rails shouldn't need those when rendering views.

Thoughts?

Erector allows nil for text content of tag/text methods

Valid in erector:

div nil
text nil
rawtext nil

Erector just uses to_s on nil, converting it to empty string. Fortitude errors.

Also noticed this difference:

div class: nil

In Erector: <div></div>
In Fortitude <div class></div>

Allow customizing view paths?

I'm using a few custom defined view paths, without going into too much detail I need to look in various <path>/app/views in addition to the standard app/views path.

I have a works-for-me hacked-up version of this available here: bigfix@f8aa0ed

It looks at the Rails paths configuration variable for app/views to pull a list of view paths to use, then loops over the old code to include files from all such locations.

return in builder's block causes closing tags to be skipped

This is kind of a bizarre case, not sure what the correct approach is. This would allow you to have some method in your widget that returns deep within html builder blocks and still have valid markup rendered.

def some_widget_method
  dt class: "hello" do
    p "Yes please"
    return
  end
end

Erector:

<dt class="hello"><p>Yes please</p></dt>

Fortitude:

<dt class="hello"><p>Yes please</p>

Still maintained?

Is this gem still maintained? Is it planned to update it to support newer Rails?

Contributing, etc.

Hey Andrew et al,

I'm the maintainer of the "modern" version of Erector, that you can find at https://github.com/ajb/erector-rails4/. We use Erector extensively at my company, and we couldn't be more excited that you're developing fortitude -- seems like you're keeping a lot of the great parts about Erector while ditching the weirder ones.

Anyway, this is more of a comment, less of a question, but whenever you have a structure in place to accept contributions, we're more than excited to start moving in the direction of using Fortitude.

Can't mark HTML attribute values as html_safe

Maybe I'm doing something wrong or reading the spec wrong, but AFAICT, special characters do not have to be HTML-escaped when inside of attribute values.

Here's Erector:

img

And here's Fortitude:

img

This came up because we were rendering a <script type='text/template'> element, and were using underscore templates (<%= variable_name >) inside of a href="" attribute.

Also, this might be an issue for data-* attributes where there may be special characters that hook into Javascript plugins?

Passing block to f.label fails in 0.9.4

@alexch and I discovered that the following code works as expected in fortitude 0.9.3 but fails in 0.9.4. Seems something gets confused when you pass f.label both args and a block.

form_for(some_obj, url: some_path(some_obj)) { |f|
   ...
   f.label(field_name, value: answer_key) { text answer_text }

Stacktrace:

     ActionView::Template::Error:
       wrong number of arguments (0 for 1+)
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/rails/yielded_object_outputter.rb:8:in `block in wrap_block_as_needed'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/helpers/capture_helper.rb:38:in `block in capture'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/helpers/capture_helper.rb:200:in `with_output_buffer'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/helpers/capture_helper.rb:38:in `capture'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/helpers/tags/label.rb:36:in `render'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/helpers/form_helper.rb:750:in `label'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/helpers/form_helper.rb:1585:in `label'
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/rails/yielded_object_outputter.rb:33:in `method_missing'
     # ./app/views/histories/edit.html.rb:76:in `block (3 levels) in history_choice'
     # (eval):32:in `tag_div'
     # ./app/views/histories/edit.html.rb:75:in `block (2 levels) in history_choice'
     # ./app/views/histories/edit.html.rb:68:in `each'
     # ./app/views/histories/edit.html.rb:68:in `block in history_choice'
     # (eval):12:in `tag_fieldset'
     # ./app/views/histories/edit.html.rb:65:in `history_choice'
     # ./app/views/histories/edit.html.rb:18:in `block (2 levels) in content'
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/rails/yielded_object_outputter.rb:10:in `call'
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/rails/yielded_object_outputter.rb:10:in `block in wrap_block_as_needed'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/helpers/capture_helper.rb:38:in `block in capture'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/helpers/capture_helper.rb:200:in `with_output_buffer'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/helpers/capture_helper.rb:38:in `capture'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/helpers/form_helper.rb:434:in `form_for'
     # (eval):3:in `form_for'
     # ./app/views/histories/edit.html.rb:12:in `block in content'
     # (eval):32:in `tag_div'
     # ./app/views/histories/edit.html.rb:11:in `content'
     # (eval):3:in `run_content'
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/widget/rendering.rb:35:in `block in render_to'
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/rendering_context.rb:79:in `record_widget'
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/widget/rendering.rb:33:in `render_to'
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/rails/renderer.rb:38:in `block (2 levels) in render'
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/rendering_context.rb:183:in `with_yield_block'
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/rails/renderer.rb:37:in `block in render'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/helpers/capture_helper.rb:200:in `with_output_buffer'
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/rails/renderer.rb:28:in `render'
     # ./app/views/histories/edit.html.rb:1:in `_app_views_histories_edit_html_rb__2472174839435550605_70144171257780'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/template.rb:145:in `block in render'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/notifications.rb:159:in `block in instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/notifications.rb:159:in `instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/template.rb:339:in `instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/template.rb:143:in `render'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/renderer/template_renderer.rb:55:in `block (2 levels) in render_template'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/renderer/abstract_renderer.rb:38:in `block in instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/notifications.rb:159:in `block in instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/notifications.rb:159:in `instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/renderer/abstract_renderer.rb:38:in `instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/renderer/template_renderer.rb:54:in `block in render_template'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/renderer/template_renderer.rb:62:in `render_with_layout'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/renderer/template_renderer.rb:53:in `render_template'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/renderer/template_renderer.rb:17:in `render'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/renderer/renderer.rb:42:in `render_template'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/renderer/renderer.rb:23:in `render'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/rendering.rb:99:in `_render_template'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/streaming.rb:217:in `_render_template'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/rendering.rb:82:in `render_to_body'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/rendering.rb:32:in `render_to_body'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/renderers.rb:32:in `render_to_body'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/abstract_controller/rendering.rb:25:in `render'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/rendering.rb:16:in `render'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/instrumentation.rb:44:in `block (2 levels) in render'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/core_ext/benchmark.rb:12:in `block in ms'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/core_ext/benchmark.rb:12:in `ms'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/instrumentation.rb:44:in `block in render'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/instrumentation.rb:87:in `cleanup_view_runtime'
     # ~/.rvm/gems/ruby-2.1.4/gems/activerecord-4.1.10/lib/active_record/railties/controller_runtime.rb:25:in `cleanup_view_runtime'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/instrumentation.rb:43:in `render'
     # ~/.rvm/gems/ruby-2.1.4/gems/fortitude-0.9.4/lib/fortitude/rails/rendering_methods.rb:85:in `render_with_fortitude'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/implicit_render.rb:10:in `default_render'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/implicit_render.rb:5:in `send_action'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/abstract_controller/base.rb:189:in `process_action'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/rendering.rb:10:in `process_action'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/abstract_controller/callbacks.rb:20:in `block in process_action'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/callbacks.rb:113:in `call'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/callbacks.rb:113:in `call'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/callbacks.rb:552:in `block (2 levels) in compile'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/callbacks.rb:502:in `call'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/callbacks.rb:502:in `call'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/callbacks.rb:86:in `run_callbacks'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/abstract_controller/callbacks.rb:19:in `process_action'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/rescue.rb:29:in `process_action'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/instrumentation.rb:32:in `block in process_action'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/notifications.rb:159:in `block in instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/activesupport-4.1.10/lib/active_support/notifications.rb:159:in `instrument'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/instrumentation.rb:30:in `process_action'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/metal/params_wrapper.rb:250:in `process_action'
     # ~/.rvm/gems/ruby-2.1.4/gems/activerecord-4.1.10/lib/active_record/railties/controller_runtime.rb:18:in `process_action'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/abstract_controller/base.rb:136:in `process'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionview-4.1.10/lib/action_view/rendering.rb:30:in `process'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/test_case.rb:595:in `process'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/test_case.rb:64:in `process'
     # ~/.rvm/gems/ruby-2.1.4/gems/actionpack-4.1.10/lib/action_controller/test_case.rb:495:in `get'
     # ./spec/controllers/histories_controller_spec.rb:18:in `block (3 levels) in <top (required)>'

Rails generator support…

…would be great! This isn't an extremely high-priority feature, but generators are one of the things that really make Rails development a joy.

:csrf_meta_tags helper unavailable?

When I have a widget that generates a raw-HTML form tag (rather than using form_for or similar helpers), I'm responsible for explicitly including CSRF-protection meta tags as hidden fields. Fine; I'd think that should just be a matter of calling the :csrf_meta_tags helper in the form (which Fortitude lists in Fortitude::Rails::Helpers.

Simple, right? Not so much…

$ docker-compose run --rm app ruby -Itest test/views/form/base_test.rb --fail-fast

# Running tests with run options --fail-fast --seed 27516:

E
Error:
Widgets::Form::Base::has a #to_html method that::with the default control_group_content parameter::renders a containing :form tag with::the correct attributes for#test_0002_accept-charset:
NoMethodError: undefined method `csrf_meta_tags' for Fortitude::Rails::Helpers:Module
    app/views/form/base.rb:33:in `csrf_protection_not_redundant'
    app/views/form/base.rb:16:in `block in content'
    app/views/form/base.rb:47:in `block in form_widget'
    app/views/form/base.rb:47:in `form_widget'
    app/views/form/base.rb:14:in `content'
    test/views/form/base_test.rb:14:in `block (3 levels) in <main>'
    test/views/form/base_test.rb:15:in `block (3 levels) in <main>'
    test/views/form/base_test.rb:32:in `block (6 levels) in <main>'

Interrupted. Exiting...


Finished tests in 0.033643s, 29.7243 tests/s, 0.0000 assertions/s.


1 tests, 0 assertions, 0 failures, 1 errors, 0 skips

What am I missing?

Directly relevant widget source here; any of these tests will demonstrate the failure (as rendering the form to HTML will fail).

Even more forms weirdness, or...

...probably I'm just having even more of a brain-dead week than usual. (Yes, I have read Issue #15, along with Issue #21 and tried to wrap my head around Commit 9d7ee0b that closed it, for what those are worth.)

Consider the following, in an otherwise thoroughly-vanilla Fortitude-fortified Rails app:

# Class encapsulating all page-specific view code for `things/new`.
class Views::Things::New < Views::Base
  needs :thing, flash: {},
                title_content: 'Add New Thing to List of All Things'

  # include SemanticLogger::Loggable
  include Fortitude::Rails::Helpers

  def content
    page_title_content
    form_for(:thing) do |f|
    end
  end

  private

  def page_title_content
    content_for :title, title_content
  end
end # class Views::Things::New

Yet when I run a simple test that uses the class, form_for is undefined:

$ bundle exec ruby -Itest test/views/things/new_test.rb 

# Running tests with run options --seed 10623:

E
Error:
Views::Things::New#test_0001_calls the #content_for helper correctly when rendered:
NoMethodError: undefined method `form_for' for #<Object:0x007fb89a611d90>
    app/views/things/new.rb:14:in `content'
    test/views/things/new_test.rb:22:in `block (2 levels) in <main>'
    test/views/things/new_test.rb:25:in `block (2 levels) in <main>'


Finished tests in 0.471040s, 2.1230 tests/s, 0.0000 assertions/s.


1 tests, 0 assertions, 0 failures, 1 errors, 0 skips

Test code:

require 'test_helper'

require File.expand_path('app/views/things/new', Rails.root)

describe 'Views::Things::New' do
  let(:described_class) { Views::Things::New }
  let(:flash) { ActionDispatch::Flash::FlashHash.new }
  let(:thing) { FactoryGirl.build_stubbed :thing }
  let(:obj) do
    described_class.new(thing: thing, flash: flash).tap do |ret|
      ret.class_eval do
        attr_reader :cf_attrib, :cf_value

        def ret.content_for(attrib, value)
          @cf_attrib = attrib
          @cf_value = value
        end
      end
    end
  end
  let(:actual) { obj.to_html }

  it 'calls the #content_for helper correctly when rendered' do
    _ = actual # nothing happens until widget is rendered, so...
    expect(obj.cf_attrib).must_equal :title
    expect(obj.cf_value).must_equal 'Add New Thing to List of All Things'
  end
end # describe 'Views::Things::New'

Line 14 of the source is, of course, the call to form_for, and Line 22 of the test (mentioned in the backtrace) is the assignment to actual which renders the widget (which is where you'd expect it to blow up, I guess). I've been beating my head against one variant or another of this for days; what am I missing (again)?

SimpleForm/custom helpers support

tried throwing this in an initializer and realized that I really don't know what's going on:

SIMPLE_FORM_FOR_YIELDED_METHODS_TO_OUTPUT =
  # https://github.com/plataformatec/simple_form/blob/6c28bf483345678e22012e576a5ab0dc440d0724/lib/simple_form/form_builder.rb
  %w{input attribute input_field association button error full_error hint label} +
  %w{error_notification collection_radio_buttons collection_check_boxes}

Fortitude::Rails::Helpers.helper(
  :simple_form_for,
  transform: :output_return_value,
  output_yielded_methods: SIMPLE_FORM_FOR_YIELDED_METHODS_TO_OUTPUT
)

Fortitude::Rails::Helpers.helper(
  :simple_fields_for,
  transform: :output_return_value,
  output_yielded_methods: SIMPLE_FORM_FOR_YIELDED_METHODS_TO_OUTPUT
)

Building needs is slow

On startup of our app a large amount of widgets are loaded immediately (asset aggregator :)), this has the side effect of causing the needs to be built up front. It adds about an extra minute to start up time to our app.

I added some basic annotation which prints whenever rebuild_my_needs_methods! is called, I noticed things like this:

...
Called rebuild_my_needs_methods! on Views::Profiles::Show 
Called rebuild_my_needs_methods! on Views::Profiles::Show 
Called rebuild_my_needs_methods! on Views::Profiles::Show 
Called rebuild_my_needs_methods! on Views::Profiles::Show 
Called rebuild_my_needs_methods! on Views::Profiles::Show 
Called rebuild_my_needs_methods! on Views::Profiles::Show 
Called rebuild_my_needs_methods! on Views::Profiles::Show 
Called rebuild_my_needs_methods! on Views::Profiles::Show 
Called rebuild_my_needs_methods! on Views::Profiles::Show 
Called rebuild_my_needs_methods! on Views::Profiles::Show 
Called rebuild_my_needs_methods! on Views::Profiles::Show 
Called rebuild_my_needs_methods! on Views::Profiles::Show 
...

Seems like there's definitely something wrong here, it appears to be redefining the methods many times over for a single widget on a large percentage of them.

Other possible things to investigate:
Can we defer needs creation until widget is used at lease once.
I noticed your simple templating language doesn't cache the templates and re-parses every time it's executed.

alias_method_chain deprecated in Rails 5

Fortitude appears to be pretty well Rails 5 compatible, with the exception of the use of alias_method_chain, which is deprecated and should be replaced with Module.prepend. Currently, running fortitude on a Rails 5 app throws a bunch of ugly deprecation warnings on app startup:

DEPRECATION WARNING: alias_method_chain is deprecated. Please, use Module#prepend instead. From module, you can access the original method using super. (called from <top (required)> at /Users/<app>/config/environment.rb:5)

Implicit passing of `needs` variables fails when View class is named the same as the `needs` key

In Erector, this works as expected:

class HomeController
  def index
   @project = Project.find(5)
  end
end

class Views::Home::Index < Views::Base
  def content
    h1 @project.name
    render 'components/project'
  end
end

class Views::Components::Project < Views::Base
  needs :project

  def content
    text @project.description
  end
end

We don't need to explicitly pass @project to the project partial, since it has needs :project declared.

However, in Fortitude, @project is nil inside of the project_details partial. Is this a bug, or am I doing something wrong?

Here's my config:

  use_instance_variables_for_assigns true
  format_output false
  start_and_end_comments false
  extra_assigns :use

use controller.view_paths to resolve view paths when calculating widget_class_from_file

in fortitude/lib/fortitude/rails/template_handler.rb you have Rails.application.paths['app/views'], which only searches path set via the configuration, and not ones added added at request time like those from prepend_view_path

view_paths can be used to get all the paths: http://api.rubyonrails.org/classes/ActionView/ViewPaths/ClassMethods.html#method-i-view_paths

The only issue with this is that it must be called in a request context, so the TemplateHandler's call method needs to be updated to do the look up at render time.

Status?

What is the status of this project? Is it still being worked on?

ArgumentError: wrong number of arguments (given 5, expected 4) with ActionView 4.2.6

I'm getting explosions from the Fortitude railtie that's monkey-patching ActionView to help it autoload view classes. Looks like the monkey-patched method inside ActionView changed the method arity but Fortitude hasn't matched? I honestly don't really understand why my particular setup isn't working because I've used other Rails projects with higher and lower versions and didn't have problems.

I also hacked Fortitude gem source and added the missing method param, passing it straight through and got everything working properly.

I'm currently on Rails 4.2.6 and attempting to use Foritude 0.9.4.

Any advice would be appreciated!

ArgumentError:
wrong number of arguments (given 5, expected 4)
# /Users/glenn/.rvm/gems/ruby-2.3.1/gems/fortitude-0.9.4/lib/fortitude/rails/railtie.rb:251:in find_templates_with_fortitude' # /Users/glenn/.rvm/gems/ruby-2.3.1/gems/actionmailer-4.2.6/lib/action_mailer/base.rb:914:ineach_template'
# /Users/glenn/.rvm/gems/ruby-2.3.1/gems/actionmailer-4.2.6/lib/action_mailer/base.rb:900:in collect_responses' # /Users/glenn/.rvm/gems/ruby-2.3.1/gems/actionmailer-4.2.6/lib/action_mailer/base.rb:829:inmail'
# ./app/mailers/application_mailer.rb:20:in mail_with_defaults' # ./app/mailers/welcome_mailer.rb:4:inwelcome_member'

Tilt integration: don't allow locals to be nil

After testing fortitude with Roda ( https://github.com/jeremyevans/roda ), fortitude blew up without explicit locals hash.

I have fixed this in roda (jeremyevans/roda#8 ), but @jeremyevans suggested to fix it also in fortitude.
My guess would be that line here:

widget_assigns = widget_assigns.merge(locals)

widget_assigns = widget_assigns.merge(locals) , would not work if locals are nil

Using #inline_html with a Rails view context

So I'm converting some Erector code to Fortitude. Outside of a normal ActionView context (say, in a model,) we've got a method that looks like this:

def to_table_cell(attachment_ids)
  Erector.inline do
    Attachment.find(attachment_ids).each do |attachment|
      a attachment.upload.raw_filename,
        href: download_attachment_path(attachment),
        target: '_blank'
    end
  end.to_html
end  # => "<a href="/attachment/12/download" target="_blank">myfile.jpg</a>"

I've noticed that Fortitude has an inline_html method, to which you can pass a block. However, it appears that since we're outside of the ActionView context, we don't have access to the download_attachment_path helper that Rails provides.

@ageweke: I've kept up a bit with the recent issue comments about rendering context... but I'm unsure if there's a way you'd recommend to implement this.

It looks like I could probably create an instance of ActionView::Base and somehow use it as my rendering context. I could probably package it up in a nice little method that would be easy to call in the future. But I feel like I'm probably doing something wrong here...

Upgraded to Rails 4.2.5.2 and everything is blowing up

I get this or similar stack trace on every test and every page render attempt. I attached my Gemfile too and am using ruby-2.3.0.

ArgumentError (wrong number of arguments (given 5, expected 4)):
fortitude (0.9.4) lib/fortitude/rails/railtie.rb:251:in find_templates_with_fortitude' actionview (4.2.5.2) lib/action_view/template/resolver.rb:116:inblock in find_all'
actionview (4.2.5.2) lib/action_view/template/resolver.rb:152:in block in cached' actionview (4.2.5.2) lib/action_view/template/resolver.rb:63:incache'
actionview (4.2.5.2) lib/action_view/template/resolver.rb:151:in cached' actionview (4.2.5.2) lib/action_view/template/resolver.rb:115:infind_all'
actionview (4.2.5.2) lib/action_view/path_set.rb:70:in block (2 levels) in _find_all' actionview (4.2.5.2) lib/action_view/path_set.rb:66:ineach'
actionview (4.2.5.2) lib/action_view/path_set.rb:66:in block in _find_all' actionview (4.2.5.2) lib/action_view/path_set.rb:65:ineach'
actionview (4.2.5.2) lib/action_view/path_set.rb:65:in _find_all' actionview (4.2.5.2) lib/action_view/path_set.rb:54:infind_all'
actionview (4.2.5.2) lib/action_view/path_set.rb:46:in find' actionview (4.2.5.2) lib/action_view/lookup_context.rb:121:infind'
actionview (4.2.5.2) lib/action_view/renderer/abstract_renderer.rb:18:in find_template' actionview (4.2.5.2) lib/action_view/renderer/template_renderer.rb:40:indetermine_template'
actionview (4.2.5.2) lib/action_view/renderer/template_renderer.rb:8:in render' actionview (4.2.5.2) lib/action_view/renderer/renderer.rb:46:inrender_template'
actionview (4.2.5.2) lib/action_view/renderer/renderer.rb:27:in render' actionview (4.2.5.2) lib/action_view/rendering.rb:100:in_render_template'
actionpack (4.2.5.2) lib/action_controller/metal/streaming.rb:217:in _render_template' actionview (4.2.5.2) lib/action_view/rendering.rb:83:inrender_to_body'
actionpack (4.2.5.2) lib/action_controller/metal/rendering.rb:32:in render_to_body' actionpack (4.2.5.2) lib/action_controller/metal/renderers.rb:37:inrender_to_body'
actionpack (4.2.5.2) lib/abstract_controller/rendering.rb:25:in render' actionpack (4.2.5.2) lib/action_controller/metal/rendering.rb:16:inrender'
actionpack (4.2.5.2) lib/action_controller/metal/instrumentation.rb:44:in block (2 levels) in render' activesupport (4.2.5.2) lib/active_support/core_ext/benchmark.rb:12:inblock in ms'
/Users/glenn/.rvm/rubies/ruby-2.3.0/lib/ruby/2.3.0/benchmark.rb:308:in realtime' activesupport (4.2.5.2) lib/active_support/core_ext/benchmark.rb:12:inms'
actionpack (4.2.5.2) lib/action_controller/metal/instrumentation.rb:44:in block in render' actionpack (4.2.5.2) lib/action_controller/metal/instrumentation.rb:87:incleanup_view_runtime'
activerecord (4.2.5.2) lib/active_record/railties/controller_runtime.rb:25:in cleanup_view_runtime' actionpack (4.2.5.2) lib/action_controller/metal/instrumentation.rb:43:inrender'
fortitude (0.9.4) lib/fortitude/rails/rendering_methods.rb:85:in render_with_fortitude' actionpack (4.2.5.2) lib/action_controller/metal/implicit_render.rb:10:indefault_render'
actionpack (4.2.5.2) lib/action_controller/metal/implicit_render.rb:5:in send_action' actionpack (4.2.5.2) lib/abstract_controller/base.rb:198:inprocess_action'
actionpack (4.2.5.2) lib/action_controller/metal/rendering.rb:10:in process_action' actionpack (4.2.5.2) lib/abstract_controller/callbacks.rb:20:inblock in process_action'
activesupport (4.2.5.2) lib/active_support/callbacks.rb:117:in call' activesupport (4.2.5.2) lib/active_support/callbacks.rb:555:inblock (2 levels) in compile'
activesupport (4.2.5.2) lib/active_support/callbacks.rb:505:in call' activesupport (4.2.5.2) lib/active_support/callbacks.rb:92:inrun_callbacks'
activesupport (4.2.5.2) lib/active_support/callbacks.rb:778:in _run_process_action_callbacks' activesupport (4.2.5.2) lib/active_support/callbacks.rb:81:inrun_callbacks'
actionpack (4.2.5.2) lib/abstract_controller/callbacks.rb:19:in process_action' actionpack (4.2.5.2) lib/action_controller/metal/rescue.rb:29:inprocess_action'
actionpack (4.2.5.2) lib/action_controller/metal/instrumentation.rb:32:in block in process_action' activesupport (4.2.5.2) lib/active_support/notifications.rb:164:inblock in instrument'
activesupport (4.2.5.2) lib/active_support/notifications/instrumenter.rb:20:in instrument' activesupport (4.2.5.2) lib/active_support/notifications.rb:164:ininstrument'
actionpack (4.2.5.2) lib/action_controller/metal/instrumentation.rb:30:in process_action' actionpack (4.2.5.2) lib/action_controller/metal/params_wrapper.rb:250:inprocess_action'
activerecord (4.2.5.2) lib/active_record/railties/controller_runtime.rb:18:in process_action' actionpack (4.2.5.2) lib/abstract_controller/base.rb:137:inprocess'
actionview (4.2.5.2) lib/action_view/rendering.rb:30:in process' actionpack (4.2.5.2) lib/action_controller/metal.rb:196:indispatch'
actionpack (4.2.5.2) lib/action_controller/metal/rack_delegation.rb:13:in dispatch' actionpack (4.2.5.2) lib/action_controller/metal.rb:237:inblock in action'
actionpack (4.2.5.2) lib/action_dispatch/routing/route_set.rb:74:in dispatch' actionpack (4.2.5.2) lib/action_dispatch/routing/route_set.rb:43:inserve'
actionpack (4.2.5.2) lib/action_dispatch/journey/router.rb:43:in block in serve' actionpack (4.2.5.2) lib/action_dispatch/journey/router.rb:30:ineach'
actionpack (4.2.5.2) lib/action_dispatch/journey/router.rb:30:in serve' actionpack (4.2.5.2) lib/action_dispatch/routing/route_set.rb:815:incall'
xray-rails (0.1.18) lib/xray/middleware.rb:38:in call' omniauth (1.3.1) lib/omniauth/strategy.rb:186:incall!'
omniauth (1.3.1) lib/omniauth/strategy.rb:164:in call' omniauth (1.3.1) lib/omniauth/builder.rb:63:incall'
meta_request (0.3.4) lib/meta_request/middlewares/app_request_handler.rb:13:in call' meta_request (0.3.4) lib/meta_request/middlewares/meta_request_handler.rb:13:incall'
rack (1.6.4) lib/rack/etag.rb:24:in call' rack (1.6.4) lib/rack/conditionalget.rb:25:incall'
rack (1.6.4) lib/rack/head.rb:13:in call' actionpack (4.2.5.2) lib/action_dispatch/middleware/params_parser.rb:27:incall'
actionpack (4.2.5.2) lib/action_dispatch/middleware/flash.rb:260:in call' rack (1.6.4) lib/rack/session/abstract/id.rb:225:incontext'
rack (1.6.4) lib/rack/session/abstract/id.rb:220:in call' actionpack (4.2.5.2) lib/action_dispatch/middleware/cookies.rb:560:incall'
activerecord (4.2.5.2) lib/active_record/query_cache.rb:36:in call' activerecord (4.2.5.2) lib/active_record/connection_adapters/abstract/connection_pool.rb:653:incall'
activerecord (4.2.5.2) lib/active_record/migration.rb:377:in call' actionpack (4.2.5.2) lib/action_dispatch/middleware/callbacks.rb:29:inblock in call'
activesupport (4.2.5.2) lib/active_support/callbacks.rb:88:in __run_callbacks__' activesupport (4.2.5.2) lib/active_support/callbacks.rb:778:in_run_call_callbacks'
activesupport (4.2.5.2) lib/active_support/callbacks.rb:81:in run_callbacks' actionpack (4.2.5.2) lib/action_dispatch/middleware/callbacks.rb:27:incall'
actionpack (4.2.5.2) lib/action_dispatch/middleware/reloader.rb:73:in call' actionpack (4.2.5.2) lib/action_dispatch/middleware/remote_ip.rb:78:incall'
airbrake (4.3.5) lib/airbrake/rails/middleware.rb:13:in call' rack-contrib (1.4.0) lib/rack/contrib/response_headers.rb:17:incall'
meta_request (0.3.4) lib/meta_request/middlewares/headers.rb:16:in call' actionpack (4.2.5.2) lib/action_dispatch/middleware/debug_exceptions.rb:17:incall'
web-console (3.1.1) lib/web_console/middleware.rb:131:in call_app' web-console (3.1.1) lib/web_console/middleware.rb:28:inblock in call'
web-console (3.1.1) lib/web_console/middleware.rb:18:in catch' web-console (3.1.1) lib/web_console/middleware.rb:18:incall'
actionpack (4.2.5.2) lib/action_dispatch/middleware/show_exceptions.rb:30:in call' railties (4.2.5.2) lib/rails/rack/logger.rb:38:incall_app'
railties (4.2.5.2) lib/rails/rack/logger.rb:20:in block in call' activesupport (4.2.5.2) lib/active_support/tagged_logging.rb:68:inblock in tagged'
activesupport (4.2.5.2) lib/active_support/tagged_logging.rb:26:in tagged' activesupport (4.2.5.2) lib/active_support/tagged_logging.rb:68:intagged'
railties (4.2.5.2) lib/rails/rack/logger.rb:20:in call' quiet_assets (1.1.0) lib/quiet_assets.rb:27:incall_with_quiet_assets'
actionpack (4.2.5.2) lib/action_dispatch/middleware/request_id.rb:21:in call' rack (1.6.4) lib/rack/methodoverride.rb:22:incall'
rack (1.6.4) lib/rack/runtime.rb:18:in call' activesupport (4.2.5.2) lib/active_support/cache/strategy/local_cache_middleware.rb:28:incall'
rack (1.6.4) lib/rack/lock.rb:17:in call' actionpack (4.2.5.2) lib/action_dispatch/middleware/static.rb:116:incall'
rack (1.6.4) lib/rack/sendfile.rb:113:in call' airbrake (4.3.5) lib/airbrake/user_informer.rb:16:in_call'
airbrake (4.3.5) lib/airbrake/user_informer.rb:12:in call' railties (4.2.5.2) lib/rails/engine.rb:518:incall'
railties (4.2.5.2) lib/rails/application.rb:165:in call' rack (1.6.4) lib/rack/content_length.rb:15:incall'
puma (2.16.0) lib/puma/server.rb:557:in handle_request' puma (2.16.0) lib/puma/server.rb:404:inprocess_client'
puma (2.16.0) lib/puma/server.rb:270:in block in run' puma (2.16.0) lib/puma/thread_pool.rb:106:inblock in spawn_thread'

Gemfile:

source 'https://rubygems.org'
ruby '2.3.0'

gem 'airbrake', '< 5'
gem 'coffee-rails'
gem 'compass-rails', '< 3'
gem 'ethereum'
gem 'faye-websocket'
gem 'fortitude'
gem 'foundation-icons-sass-rails'
gem 'foundation-rails', '< 6'
gem 'jbuilder'
gem 'jquery-rails'
gem "nilify_blanks"
gem 'nokogiri'
gem 'omniauth-slack'
gem 'omniauth'
gem 'pg'
gem 'postmark-rails'
gem 'premailer-rails'
gem 'puma'
gem 'pundit'
gem 'rails_12factor', group: :production
gem 'rails', '4.2.5.2'
gem "refile", require: "refile/rails"
gem "refile-mini_magick"
gem "refile-s3"
gem 'responders'
gem 'sass-rails'
gem 'sdoc', group: :doc
gem 'slack-ruby-client'
gem 'sucker_punch'
gem 'uglifier'

group(:test) do
gem 'webmock'
gem 'vcr'
end

group(:development, :test) do
gem 'awesome_print'
gem 'capybara'
gem 'database_cleaner'
gem 'dotenv-rails'
gem 'faker'
gem 'fuubar'
gem 'guard-rspec', require: false
gem 'phantomjs', require: 'phantomjs/poltergeist'
gem 'poltergeist'
gem 'pry-byebug'
gem 'pry-rails'
gem 'rack_session_access'
gem 'rspec-rails'
gem 'selenium-webdriver'
gem 'simplecov'
gem 'typhoeus'
end

group(:development) do
gem 'git-storyid'
gem 'html2fortitude'
gem 'letter_opener'
gem 'meta_request'
gem 'quiet_assets'
gem 'spring-commands-rspec'
gem 'spring'
gem 'web-console'
gem 'xray-rails'
end

Rendering an Erector widget from inside Fortitude

Kinda a weird use case, I'll admit, but as we're converting over our applications from Erector -> Fortitude, they still have dependencies that include Erector widgets. I thought it would be as easy as:

class FortitudeWidget < Views::Base

  def content
    rawtext ErectorWidget.new.to_html
  end

end

But the problem is that the ErectorWidget doesn't have access to the helpers object, so if it tries to reference e.g. current_user, it fails.

Any advice on how to pass in either parent or helpers? Here a link to some related lines in the Erector codebase.

Capture does not work in render :widget

When rendering with render widget: Views::MyWidget I noticed that running capture returns nil and leaves the output on the existing output buffer. If I force _fortitude_builtin_capture to run then it works.

Looking deeper, the rails implementation of capture uses this method:

def with_output_buffer(buf = nil) #:nodoc:
  unless buf
    buf = ActionView::OutputBuffer.new
    buf.force_encoding(output_buffer.encoding) if output_buffer.respond_to?(:encoding) && buf.respond_to?(:force_encoding)
  end
  self.output_buffer, old_buffer = buf, output_buffer
  yield
  output_buffer
ensure
  self.output_buffer = old_buffer
end

This works for the output buffer stored on helpers, which is used by fortitude in a normal render. But with render :widget we are rendering to string with our own internal fortitude output buffer, so this method doesn't have right effect.

'uninitialized constant' errors

We consistently get errors when Rails tries to reload views in development mode. The files load correctly the first time, but throw an 'uninitialized constant' error the second time.

For example:

We have the following directory structure:

app/views/base.rb

module Views
  class Base < Fortitude::Widget
    doctype :html5
    ...
  end
end

app/views/logged_out/index.html.rb

class Views::LoggedOut::Index < Views::Base
  include Views::Shared::AuthPanel
  def content
    ...
  end
end

The exception we get is:

ActionView::Template::Error (uninitialized constant Views::LoggedOut::Index):
    1: class Views::LoggedOut::Index < Views::Base
    2:   include Views::Shared::AuthPanel
    3:
    4:   def content
  app/views/logged_out/index.html.rb:1:in '_app_views_logged_out_index_html_rb__3228983590333935155_70328782437080'

If we rename the file to be app/views/logged_out/index.rb instead of .html.rb, the problem goes away. However, we need the .html so that Rails doesn't try to use the fortitude views to render json responses.

render widget: Views::Hello does not work as expected

  • The delegate_object you use for the rendering_context is a controller instance instead of the view_context, so view helpers are not available (and other weird stuff happens)
  • If you have Erector installed alongside Fortitude, because you don't strip the :widget option, Erector tries to render the Fortitude widget somewhere deep within render_without_fortitude
  • Passing a class instead of an instance does not work (it should use view_context.assigns for needs by default)
  • After patching some of these things, I was unable it to make it actually work at all. It manipulates the options with the :text option correctly, but my layout still renders empty. (I noticed if I disabled the layout then the content would come through)

Lastly, I'm curious why you chose to do it the way you did, Erector does the following to register a :widget renderer:

require 'action_controller/metal/renderers'

ActionController.add_renderer :widget do |widget, options|
  # return result of render
end

Global configuration

In the erector doc, you mention this:

Configure all options on a per-class basis with inheritance (zero "across-the-board" global settings);

I certainly understand why this is attractive, but maybe you can help me understand how to properly implement this use case:

  • All of my widgets use the html5 doctype
  • I don't want the start_and_end_comments, ever
  • I have a bunch of view components that inherit from Fortitude::Widget

What's the best way to ensure that all of my components receive these options? Should I subclass Fortitude::Widget to Fortitude::MyWidget, that has my configuration applied? (Seems messy.) Should I apply my configuration directly to the Fortitude::Widget? (This seems wrong.) Do I inherit from Fortitude::Widgets::Html5? (Too many characters, doesn't have my config.)

Caching

I wrote this caching module for erector-rails4, which adds all of the neat cache_digests stuff to widgets. What's even cooler about using cache_digests in Erector is that because your needs are explicit, you can calculate the cache_key for a widget without having to manually specify the objects it depends on.

Is this something you'd be interested in implementing in fortitude? Anything about the implementation that you'd want to change?

Unit testing of widgets?

With Erector, as demonstrated in their specs, testing widgets using #to_html, #to_a, etc, was drop-dead simple. Writing simple tests like

    it 'renders the expected content' do
      expect(FooWidget.new.to_html).must_equal expected_content
    end

would Just Work. Fortitude adds an internal, apparently-undocumented rendering context that leads the above MiniTest::Spec code to fail with the obviously-intended-to-be-helpful message

Fortitude::Errors::NoBlockToYieldTo: You're trying to call 'yield' (or 'yield_from_widget', or the Erector-compatibility method 'call_block')
from the widget #<Views::FooWidget:xxxxxxxx>; however, there is nothing to yield to. Fortitude
looks for something to yield to in this order:
  1. A block passed to a yield at render time directly (usually via the 'widget' call);
  2. A block passed to the constructor of the widget;
  3. The layout the widget is being rendered in.
None of these exist here, and so calling 'yield', 'yield_from_widget', or 'call_block' is an
undefined operation.

So what should I be doing instead to unit-test a widget? Isn't the whole point of "Views Are Code" supposed to be that we can treat widgets and widget-derived code like pages the same as any other classes in our system — with testing, composition, SOLID, and so on? Of course feature specs work, but that's only half the job.

What has everybody else been doing?

Programmatic selection of child widgets?

Let's say I have a FullNavbar widget, that needs to display one of multiple Menu::Whatever widgets based on conditions determined outside itself that it shouldn't have any reason to be privy to. "Fine," I think, "I'll just assign a widget class to a menu_adder needs variable (change in strategy); the Navbar will at some point have the line widget menu_adder, and all will be fine and dandy. A five-minute job."

"A five-minute job" as in SS Minnow's "three-hour tour", apparently...

The error as reported by MiniTest::Spec running my specs, along with the first lines of stack dump down to my widget code, are

Widgets::Page::FullNavbar::renders markup via the #to_html method that::by default::has a wrapper element::contains a Bootstrap container that::contains a "navbar-collapse" :div which::contains a "navbar-collapse" :div that::contains a :ul element that#test_0001_has the correct CSS classes:
RuntimeError: can't modify frozen #<Class:#<Class:0x007fe5363a77a8>>
    /path/to/the_app/vendor/ruby/2.2.0/gems/fortitude-0.9.4/lib/fortitude/widget/needs.rb:60:in `needs_as_hash'
    /path/to/the_app/vendor/ruby/2.2.0/gems/fortitude-0.9.4/lib/fortitude/widget/needs.rb:127:in `rebuild_my_needs_methods!'
    /path/to/the_app/vendor/ruby/2.2.0/gems/fortitude-0.9.4/lib/fortitude/widget/needs.rb:116:in `block in ensure_needs_methods_are_valid!'
    /path/to/the_app/vendor/ruby/2.2.0/gems/activesupport-4.2.3/lib/active_support/notifications.rb:166:in `instrument'
    /path/to/the_app/vendor/ruby/2.2.0/gems/fortitude-0.9.4/lib/fortitude/widget/integration.rb:14:in `rebuilding'
    /path/to/the_app/vendor/ruby/2.2.0/gems/fortitude-0.9.4/lib/fortitude/widget/needs.rb:115:in `ensure_needs_methods_are_valid!'
    (eval):2:in `assign_locals_from'
    /path/to/the_app/vendor/ruby/2.2.0/gems/fortitude-0.9.4/lib/fortitude/widget/rendering.rb:85:in `initialize'
    /path/to/the_app/vendor/ruby/2.2.0/gems/fortitude-0.9.4/lib/fortitude/widget/rendering.rb:58:in `new'
    /path/to/the_app/vendor/ruby/2.2.0/gems/fortitude-0.9.4/lib/fortitude/widget/rendering.rb:58:in `widget'
    /path/to/the_app/app/views/page/full_navbar.rb:57:in `block in navbar_menu'

The mentioned line 57 is the widget call in

module Widgets
  module Page
    class FullNavbar < Views::Base
      needs menu_adder

      # ...

      def navbar_menu
        ul(class: 'nav navbar-nav') do
          widget menu_adder
        end # ul
      end
    end # class
  end
end

Any ideas on how to go about tackling this sort of thing? Or should I go back to my original plan and pass in a lambda for menu_adder rather than a widget?

How to access (Rails controllers') flash messages?

Erector's Rails integration, IIRC, gave you a controller accessor that you could call #flash on to retrieve flash messages. I've been stumped for a full day on how to access flash messages inside a Fortitude page widget. What am I missing?

'superclass mismatch' errors

I often get 'superclass mismatch' errors after modifying and reloading templates in development mode.

The file structure is:

app/views/foo/edit.html.rb

module Views
  module Foo
    class Edit < Views::Base
      def content
        widget(Views::Foo::Form, ...)
      end
    end
  end
end

app/views/foo/form.rb

module Views
  module Foo
    class Form < Views::Base
      def content
        ...
      end
    end
  end
end

The error is:

ActionView::Template::Error (superclass mismatch for class Edit):
    1: module Views
    2:   module Foo
    3:     class Edit < Views::Base
app/views/foo/edit.html.rb:3:in `<module:Foo>'
...
activesupport (4.1.6) lib/active_support/dependencies.rb:225:in `require_dependency'
.../.rvm/gems/ruby-2.1.2/bundler/gems/fortitude-11a268dda85d/lib/fortitude/rails/template_handler.rb:7:in `call'
...

The exact issue is the widget line. Theoretically I should be able to refer to either Views::Foo:Form, or just Form since we're in the Views::Foo namespace. And indeed, if I start the server with either of those, and don't touch that line, things work great. However, if I change from one format to the other, the error pops up. In fact, from then on, even if I change back to the original format, Rails keeps throwing the error when it tries to load the app/views/foo/edit.html.rb file. It's as if loading the widget file a second time in a slightly different way causesViews::Base to end up with two different definitions.

I can resolve the issue by adding require_dependency 'views/base' at the top of the templates.

System info:

$ ruby -v
ruby 2.1.2p95 (2014-05-08 revision 45877) [x86_64-darwin13.0]
$ rails -v
Rails 4.1.6

Unit testing of widgets without loading entire Rails stack in test environment?

(Largely a conceptual variation on #28)

Is it possible to test rendering of widgets from "fast Ruby" tests that don't load the entire Rails environment, or is (what I assume to be) the ActionView dependency dependent on enough outside Rails "magic" to be pulled out by itself reasonably? Has anyone successfully accomplished this?

Single arity template handlers are deprecated in Rails 6.0

Getting following deprecation warning when using fortitude with Rails 6.0.0

DEPRECATION WARNING: Single arity template handlers are deprecated. Template handlers must
now accept two parameters, the view object and the source for the view object.
Change:
  >> #<Fortitude::Rails::TemplateHandler:0x000055c7f4ffcc58>.call(template, block)
To:
  >> #<Fortitude::Rails::TemplateHandler:0x000055c7f4ffcc58>.call(template, block, source)
 (called from <top (required)> at config/application.rb:7)

Static Undefined Method

The static method only seems to work if a super class defines it.

For example,
Views:: Base
def main
end

Views::Layouts::Page < Views::Base
static :main
static :intro

def main
end

def intro
end

This will result in undefined method `intro'

Widgets are broken

Sorry, I think this was introduced during the fix of #3...

This line throws a 'No such file or directory' error when I try to render Widgets.

The file structure is:

app/views/foo/edit.html.rb

module Views
  module Foo
    class Edit < Views::Base
      needs :bar

      def content
        widget(Form, bar: bar)
      end
    end
  end
end

app/views/foo/form.rb

module Views
  module Foo
    class Form < Views::Base
      needs :bar

      def content
        text bar.baz
      end
    end
  end
end

The error is:

ActionView::Template::Error:
       No such file or directory @ dir_initialize - .../app/views/foo/edit
     # .../.rvm/gems/ruby-2.1.2/gems/fortitude-0.0.6/lib/fortitude/rails/railtie.rb:154:in `open'
     # .../.rvm/gems/ruby-2.1.2/gems/fortitude-0.0.6/lib/fortitude/rails/railtie.rb:154:in `entries'

It looks like fortitude is interpreting some of the file name (edit) as part of the directory structure.

retina_images repo unavailable

I'm trying to build the middleman documentation but retina_images is missing. I see the parcels repo on GitHub but not retina_images.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.