chamnap / liquid-rails Goto Github PK
View Code? Open in Web Editor NEWRenders liquid templates with layout and partial support
Home Page: https://rubygems.org/gems/liquid-rails
License: MIT License
Renders liquid templates with layout and partial support
Home Page: https://rubygems.org/gems/liquid-rails
License: MIT License
Rails 5.0.0
, Liquid 4.0.0rc2
--
C:/Dev/Dependencies/Ruby/ruby-2.3.0-x64-mingw32/lib/ruby/gems/2.3.0/gems/bundler-1.12.5/lib/bundler/runtime.rb:89:in `rescue in block (2 levels) in require': There was an error while trying to load the gem 'liquid-rails'. (Bundler::GemRequireError)
Gem Load Error is: Liquid error: Filter overrides registered public methods as non public: h
Any advice?
With an app we're currently building, we use a Panoramic resolver to pull our templates from the database instead of the filesystem, as we allow templates to be changed on the fly.
Our main problem is that liquid-rails doesn't pull templates using the resolver, for any templates included inside other templates. The main template called from the rails controller itself pulls from the database fine, but the partials that are included inside that template continue to pull from the filesystem instead.
Any thoughts on ways to get this working?
Hello!
In rails i can write
link_to 'this is a link', root_url, :class => 'css-class'
My question is how can i call link_to filter inside liquid template?
Thanks
First off, I want to thank @chamnap for creating and maintaining this gem. It has been incredibly helpful to us in adding Liquid support to our current rails project.
Is there any interest in support for Liquid 4? I saw the comment on Shopify/liquid#441 which indicated that 4.0.0 had a breaking change with how this gem resolves template and partial paths. I spent a day or two on it, and I wound up creating and passing a Liquid::Context into my Resolver class when it's set in ApplicationController. That works for me because the context won't change within a single request in my app.
If anyone else is working on Liquid 4 support, I'd love to hear how you have approached it.
I'm trying to render inline using liquid pulled from the DB. Anyway to pass the controller context when doing this?
Within controller:
template = Liquid::Template.parse(data_from_db)
render inline: template.render
If the template has something similar to {{ val | number_to_currency }}, I'll receive an error:
Liquid error: Liquid::Rails::NumberFilter#number_to_currency delegated to h.number_to_currency, but h is nil:
Pull requests ignored and no commits in almost a year. Is liquid-rails dead?
Assume that in rails we can do something like this
<%= render :partial => 'my_partial', :locals => { :my_var => 'value' } %>
How can do this in liquid?
Thanks
Hi Chamnap,
Thank you for making this library. I have been working with the code and have a working prototype for implementing the layout tag similar to what shopify has: https://help.shopify.com/en/themes/liquid/tags/theme-tags#layout (I doubt my implementation is the same)
My method was this:
class Liquid::Tags::LayoutTag < Liquid::Tag
def initialize(tag_name, markup, tokens)
super
@template = markup.delete("\"").strip
end
def render(context)
context.environments.first["layout_override_filename"] = @template
""
end
end
class TemplateHandler
def self.call(template)
"Liquid::Handlers::TemplateHandler.new(self).render(#{template.source.inspect}, local_assigns)"
end
def initialize(view)
@view = view
@controller = @view.controller
@helper = ActionController::Base.helpers
end
def render(template, local_assigns={})
assigns = if @controller.respond_to?(:liquid_assigns, true)
@controller.send(:liquid_assigns)
else
@view.assigns
end
# check if there is a layout override
layout_override_filename = assigns["layout_override_filename"]
# if we are processing the layout and there is an override, replace the template with the override content.
if @view.content_for?(:layout) && !layout_override_filename.nil?
Rails.logger.info "Rendering layout override from #{layout_override_filename}"
template = read_template_from_file_system(registers, layout_override_filename)
end
assigns['content_for_layout'] = @view.content_for(:layout) if @view.content_for?(:layout)
assigns.merge!(local_assigns.stringify_keys)
liquid = Liquid::Template.parse(template)
liquid.send(render_method, assigns, filters: filters, registers: registers).html_safe
end
def filters
if @controller.respond_to?(:liquid_filters, true)
@controller.send(:liquid_filters)
else
[@controller._helpers]
end
end
def registers
{
view: @view,
controller: @controller,
helper: @helper,
file_system: Liquid::Handlers::FileSystem.new(@view)
}
end
def compilable?
false
end
def render_method
(::Rails.env.development? || ::Rails.env.test?) ? :render! : :render
end
def read_template_from_file_system(registers, name)
file_system = registers[:file_system] || Liquid::Template.file_system
file_system.read_template_file(name)
end
end
The template handler then replaces the view with the select template when rendering occurs. This was really just a proof of concept. If I clean this up and submit it as a pull request would that be useful to you or others do you think?
Any suggestions on improvements? Liquid is very new to me and I had troubles finding a good way to pass the template override through and ended up using the environment.
I notice that the rails templates are not cacheable. This makes the template get re-read from disk, then parsed every time the view is rendered, which is slow.
I understand that rails template compilable implies you are returning the function as source code (which is unacceptable), but I was wondering if it made sense to memoize the "parse" function, so that it returns the same template?
The render-ing function would have to be a pure function. Thus, I think, you'd have to use the render! function, as the render mutates the templates with errors.
Hi @radin-reth
I hold my templates in app/templates and when attempt to include partials inside that directory i'm getting error about "No such template 'v14/html/shared/region_select'" .
Is there way to change default template location?
thanks
Hello! I'm running into some issues when using a has_many :through
association and I was wondering if you could point me in the right direction. I've got a model association like this:
class Page < ActiveRecord::Base
has_many :block_associations, as: :blockable, dependent: :destroy
has_many :blocks, through: :block_associations
end
class Block < ActiveRecord::Base
belongs_to :block_type
has_many :block_associations
end
class BlockAssociation < ActiveRecord::Base
belongs_to :block
belongs_to :blockable, polymorphic: true
default_scope { order(sort_order: :asc) }
end
My drop setup for the Page model is also fairly straightforward:
class PageDrop < Liquid::Rails::Drop
has_many :blocks
end
However, when I reference page.blocks
in the template, the ordering is not honoring the order set by the default_scope
in the BlockAssociation model. Looking through the logs, I'm seeing these queries:
BlockAssociation Load (1.2ms) SELECT "block_associations".* FROM "block_associations" WHERE "block_associations"."blockable_type" = 'Page' AND "block_associations"."blockable_id" IN (2) ORDER BY "block_associations"."sort_order" ASC
Block Load (0.5ms) SELECT "blocks".* FROM "blocks" WHERE "blocks"."id" IN (377, 305, 6765, 278, 604)
It looks like the block IDs are being retrieved and then a single query to get the blocks is done, but that leads to the blocks being sorted by ID, not by the sort_order
field set on the BlockAssociation join table.
The typical query as generated by ActiveRecord is as follows:
SELECT "blocks".* FROM "blocks" INNER JOIN "block_associations" ON "blocks"."id" = "block_associations"."block_id" WHERE "block_associations"."blockable_id" = $1 AND "block_associations"."blockable_type" = $2 ORDER BY "block_associations"."sort_order" ASC [["blockable_id", 2], ["blockable_type", "Page"]]
Unfortunately, all I've been able to figure out so far is to define a method to return the blocks manually:
def blocks
@object.blocks.order('block_associations.sort_order ASC')
end
That, of course, generates another SQL query. Any thoughts on how I could fix this, or maybe point me towards the code? Thanks!
I would be helped with the layout tag, like this (Shopify): https://docs.shopify.com/themes/liquid-documentation/tags/theme-tags#layout
Hi,
What's the difference between the with: "DropName" and class_name: "DropName" options available when declaring Drop associations? I couldn't tell from the spec + fixture.
Hello
I have a helper in applicatioon_helper.rb that returns named url (page_url). This helper available from liquid template, but gets error that named url (In my case page_url) not defined.
Is there a solution to this?
Thanks
I added a filter to use form_tag in liquid template and registered it but after invoking it in template it accepts first parameter only
module Liquid
module Rails
module FormTagFilter
delegate :form_tag, :hidden_field_tag, to: :h
private
def h
@h ||= @context.registers[:view]
end
end
end
end
Liquid::Template.register_filter(Liquid::Rails::FormTagFilter)
{{ '/posts', remote = true | form_tag }}
{{ end }}
Adding the above code to liquid template it accepts the first parameter only the other parameters passed to form_tag doesn't show up.
I've just found that some of my liquid-templated outbound email is being junked, and the root cause is because Liquid::Rails::TemplateHandler#render sets the Content-Type for the entire view to text/html, which overrides the multipart/alternative that ActionMailer would normally use.
As a result, services like Hotmail, Gmail perceive an HTML-only message and this raises the spam score.
Any particular reason why this is so? After all liquid templates are generic, they're not just HTML, so it's a false assumption.
I've also just tested using a .liquid partial in a .text.erb template and found that this too incorrectly turns a text/plain response into text/html response. So this something that could change browser behaviour.
Hello everyone,
i'm using rails 5 with liquid 3.0.6 and liquid-rails 0.1.3
i'm trying to render a template in which i included a picture field (carrierwave).
I have an error "Liquid error: undefined method `to_liquid' for #PictureUploader:0xa91e2f0"
My question is how to render an image inside template using carrierwave ?
Thanks in advance
Hello! Looks like Rails 6 has a slight change in template handler signature.
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:
>> Liquid::Rails::TemplateHandler.call(template)
To:
>> Liquid::Rails::TemplateHandler.call(template, source)
(called from <top (required)> at <...>/config/environment.rb:7)
When I run the rails generate scaffold_controller Foo name:string
I get an error liquid [not found]
.
$ rails g scaffold_controller Foo name:string
create app/controllers/foos_controller.rb
error liquid [not found]
invoke test_unit
create test/controllers/foos_controller_test.rb
create test/system/foos_test.rb
invoke helper
create app/helpers/foos_helper.rb
invoke test_unit
invoke jbuilder
create app/views/foos
create app/views/foos/index.json.jbuilder
create app/views/foos/show.json.jbuilder
create app/views/foos/_foo.json.jbuilder
Since it fails on "liquid", wondering if the issue may be related to this gem...
I don't really expect it to be scaffolding any liquid templates, I just want my typical .erb templates generated.
In droppable.rb, safe_constantize
is used. This means that whenever you call some_rails_model.to_liquid
, instead of throwing a NameError: unitialized constant SomeRailsModelDrop
, we get NoMethodError: undefined method
new' for nil:NilClass`
So, I think that constantize
would be better here than safe_constantize
.
Hi! Just found this gem as I am looking to use Liquid in my Rails 6 app. It looks like it hasn't been updated in 2 years tho. Is it because it still just works or because it's no longer maintained?
Thanks in advance
rails_50.gemfile
and rails_51.gemfile
both require update to .translate
method's second argument, switching it from options.with_indifferent_access
to **options.to_sym
rails_52.gemifle
fails every test with this stacktrace:
Failure/Error: super
NoMethodError:
undefined method `run_callbacks' for #<RSpec::ExampleGroups::Request::CustomActionviewResolver:0x00007f8ec3db3dd8>
We have a project that has some classes in app/filters
and consequently spec/filters
that have nothing to do with Liquid, but the liquid-rails gem makes the assumption that whatever is in a filters
directory relates to Drop filters. This should probably be a manual configuration option that you need to explicitly make in your RSpec configuration rather than something that is done automagically, as it is a simple configuration process and does not need to happen implicitly.
Hello,
I haven't figured out how to render an attribute of an instance variable that contains a database record. What am I missing?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.