Undefined method `default_url_options' when using Component and Phlex::Rails #767
-
Hi, i am exploring Phlex with Rails. I wanted to render component inside view, with some logic about paths, but for some reason I get class Articles::NewView < ApplicationView
attr_reader :article
def initialize(article:)
@article = article
end
def view_template
h1 { "New article" }
render Articles::FormComponent.new(article: article)
end
end The component looks like this: class Articles::FormComponent < ApplicationComponent
attr_reader :article, :action, :method
def initialize(article:)
@article = article
if article.persisted?
@action = article_path(article) # Here
@method = :patch
else
@action = articles_path() # and here
@method = :post
end
end
def view_template
# template content...
end
end My ApplciationComponent looks like this: class ApplicationComponent < Phlex::HTML
include Phlex::Rails::Helpers::Routes
include Phlex::Rails::Helpers::LinkTo
if Rails.env.development?
def before_template
comment { "Before #{self.class.name}" }
super
end
end
end What's interesting defining 2 methods allowed me to render view class Articles::FormComponent < ApplicationComponent
def url_options
{}
end
def default_url_options
{}
end
end I am wondering is it a potential bug or just my poor skills :D |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments 1 reply
-
That’s very strange. Should be handled by the inclusion of the I expect something is going wrong way before we get to this helper. How are you rendering render Articles::NewView.new(
article: Article.new
) |
Beta Was this translation helpful? Give feedback.
-
Yeah exactly
|
Beta Was this translation helpful? Give feedback.
-
Oh, I know what it is! We should really call this out in the guides. You can’t use helpers from the initializer, because the initializer happens when the component is created, not when it’s rendered. We don’t have a rendering context at that point. If we write the controller action like this, it’s more apparent. component = Articles::NewView.new(
article: Article.new
)
# the initializer has run at this point, but it doesn’t have a rendering context
render(component)
# now it has a rendering context but it’s too late The solution is to move that logic out. class Articles::FormComponent < ApplicationComponent
attr_reader :article, :action, :method
def initialize(article:)
@article = article
end
def before_template
super # it’s good practice to call this from before_template callbacks
if @article.persisted?
@action = article_path(@article)
@method = :patch
else
@action = articles_path
@method = :post
end
end
def view_template
# template content...
end
end Alternatively, you could calculate these on the fly class Articles::FormComponent < ApplicationComponent
def initialize(article:)
@article = article
end
def view_template
# template content...
end
private
def action
@article.persisted? ? article_path(@article) : articles_path
end
def method
@article.persisted? ? :patch : :post
end
end Unrelated, I recommend avoiding |
Beta Was this translation helpful? Give feedback.
-
Thanks for help and advice, will try out when back home
|
Beta Was this translation helpful? Give feedback.
Oh, I know what it is! We should really call this out in the guides. You can’t use helpers from the initializer, because the initializer happens when the component is created, not when it’s rendered. We don’t have a rendering context at that point.
If we write the controller action like this, it’s more apparent.
The solution is to move that logic out.