Open wlipa opened 8 years ago
I also reproduced this exact error.
I believe this bug was introduced from this commit: https://github.com/sferik/rails_admin/commit/fe2899fdeb48f4cdf33c0616f0024df13fd32f14
The problem is that it tries to run JSON.parse(value) even when it's not valid JSON.
:+1: for @kevinryantao solution
I guess JSONB should be non-queryable. Can someone provide a PR?
It's not that it should be non-queryable, but rather it should be coerced into text.
is this fixed? this seems like something a lot of people would run into
👍 for this issue
Until this is fixed you could use this workaround in your configuration:
ActiveRecord::Base.descendants.each do |model|
config.model "#{model.name}" do
exclude_fields_if { type == :json }
end
end
That seems to exclude it always. Anyway to just exclude that in searches?
-- Sent from my mobile
On Sep 5, 2016, at 10:21 AM, Mario Pérez notifications@github.com wrote:
Until this is fixed you could use this workaround in your configuration:
ActiveRecord::Base.descendants.each do |model| config.model "#{model.name}" do exclude_fields_if { type == :json } end end — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.
@jtoy Yes. This will exclude it for all the models that have json columns
@mapreal19 i couldn't get this working, are you using this?
@jtoy I ended up making those json attrs non-queryable. Give this a try:
ActiveRecord::Base.descendants.each do |model|
config.model(model.name.to_s) do
fields_of_type(:json) { queryable false }
end
end
this works, thank you!
On Sep 22, 2016, at 3:11 AM, Mario Pérez notifications@github.com wrote:
@jtoy https://github.com/jtoy I ended up making those json attrs non-queryable. Give this a try:
ActiveRecord::Base.descendants.each do |model| config.model(model.name.to_s) do fields_of_type(:json) { queryable false } end end — You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/sferik/rails_admin/issues/2502#issuecomment-248829117, or mute the thread https://github.com/notifications/unsubscribe-auth/AAA5v55JCy-bEDljou-OqThN7uqNXNudks5qsioXgaJpZM4GyFQ_.
Note for Rails 5 (or any situation where you have an abstract model defined like ApplicationRecord), you'll need to skip abstract classes:
ActiveRecord::Base.descendants.each do |model|
next if model.abstract_class?
config.model(model.name.to_s) do
fields_of_type(:json) { queryable false }
end
end
Also don't forget you'll probably need to eager load your models beforehand (Rails.application.eager_load!
), otherwise they won't be found as descentendants of ActiveRecord::Base
when that code runs
@jtoy thanks for the workaround, should this go in an initializer or in dev/prod/test.rb? I've tried to add it to a rails_admin.rb initializer and to development.rb file but none worked.
@MatthiasRMS Did you eager load your models beforehand as @fny suggested?
Rails.application.eager_load!
ActiveRecord::Base.descendants.each do |model|
next if model.abstract_class? # comment out this line if you are on Rails < 5
config.model(model.name.to_s) do
fields_of_type(:json) { queryable false }
end
end
Here is my workaround, in an initializer:
RailsAdmin::Config::Fields::Types::Json.inspect # Load before override.
class RailsAdmin::Config::Fields::Types::Json
def queryable?
false
end
end
None of the above worked for me. This fixed it:
RailsAdmin.config do |config|
ApplicationRecord.descendants.each do |model|
next if model.abstract_class?
config.model(model.name.to_s) do
exclude_fields_if do
type == :json
end
exclude_fields_if do
type == :jsonb
end
end
end
end
@MatthiasRMS solution worked for us with small tweaks:
Rails.application.eager_load!
ActiveRecord::Base.descendants.each do |model|
next if model.abstract_class?
config.model(model.name.to_s) do
exclude_fields_if do
[:json, :jsonb].include?(type)
end
end
end
I improved on @sbull's solution by making it work with the current rails_admin version (1.4.2) at the time of writing:
# Prevent json fields from being queried, since RailsAdmin cannot handle them
RailsAdmin::Config::Fields::Types::Json.inspect
class RailsAdmin::Config::Fields::Types::Json
register_instance_option :queryable? do
false
end
end
The advantage of this technique is that it does not force you to eager load your app.
Alternatively the following code works too, and does not crash with a 500 error if you enter bad JSON data in a RailsAdmin form:
# Don't blow up RailsAdmin on JSON searches or invalid JSON formats
class RailsAdmin::Config::Fields::Types::Json
register_instance_option :formatted_value do
if value.is_a?(Hash) || value.is_a?(Array)
JSON.pretty_generate(value)
else
value
end
end
def parse_value(value)
value.present? ? JSON.parse(value) : nil
rescue JSON::ParserError
value
end
end
This seems to prevent an error, but even when I put in a valid JSON value to query by, the query by doesn't actually search the JSON field (it just returns no records), or if I filter specifically by the JSON field (an array in my case), it returns all records, regardless of a match.
This above solution seems to prevent rails_admin from render any JSON, Any recommendation on how to return it as plain text?
I think I found a way of hacking the search function to work with JSONB fields. It casts the entire JSONB field as text, which means your search will also include key names.
list do
field :field_name, :string do
queryable true
searchable_columns [{ column: "field_name::TEXT", type: :string }]
end
end
Hope this helps! Maybe someone else can figure out how to eliminate the key names? And maybe this could also serve as the foundation for a more general solution that can be integrated into the core project?
Edit: I don't mean to pass the buck on this. I've just spent half a day trying to figure this out and I'm zonked right now.
If you search / query a model with a jsonb field, and your search query is plain text (like "aa"), then the server will throw a JSON parser exception like the following:
A workaround is to configure the json field as non-queryable.