fixture_builder icon indicating copy to clipboard operation
fixture_builder copied to clipboard

How to handle JSONB columns on name-spaced tables?

Open jackkinsella opened this issue 6 years ago • 3 comments

Here's the situation: Imagine you have a name-spaced table, e.g. admin_users, representing the model Admin::User, and this table has a JSONB column, say details.

The fixture_builder gem won't ever call serialized_value_if_needed. The key method is dump_tables in builder.rb, which calculates the class name with the following code:

   table_klass = table_name.classify.constantize rescue nil

The trace is as follows:

"admin_users".classify => "AdminUser" # should be "Admin::User"
"AdminUser".constantize => error 

Any ideas how to handle this?

jackkinsella avatar Jul 24 '18 10:07 jackkinsella

I also tried naming the table admin/users, but fixture_builder gave the following error trace (which was fixable by manually creating a spec/fixtures/admin folder):

Errno::ENOENT: No such file or directory @ rb_sysopen - /Users/jack/code/PROJECT/spec/fixtures/admin/users.yml
/Users/jack/.rvm/gems/ruby-2.5.0/gems/fixture_builder-0.5.1/lib/fixture_builder/builder.rb:151:in `initialize'
/Users/jack/.rvm/gems/ruby-2.5.0/gems/fixture_builder-0.5.1/lib/fixture_builder/builder.rb:151:in `open'
/Users/jack/.rvm/gems/ruby-2.5.0/gems/fixture_builder-0.5.1/lib/fixture_builder/builder.rb:151:in `write_fixture_file'
/Users/jack/.rvm/gems/ruby-2.5.0/gems/fixture_builder-0.5.1/lib/fixture_builder/builder.rb:90:in `block in dump_empty_fixtures_for_all_tables'
/Users/jack/.rvm/gems/ruby-2.5.0/gems/fixture_builder-0.5.1/lib/fixture_builder/builder.rb:89:in `each'
/Users/jack/.rvm/gems/ruby-2.5.0/gems/fixture_builder-0.5.1/lib/fixture_builder/builder.rb:89:in `dump_empty_fixtures_for_all_tables'
/Users/jack/.rvm/gems/ruby-2.5.0/gems/fixture_builder-0.5.1/lib/fixture_builder/builder.rb:65:in `write_data_to_files'
/Users/jack/.rvm/gems/ruby-2.5.0/gems/fixture_builder-0.5.1/lib/fixture_builder/builder.rb:17:in `generate!'
/Users/jack/.rvm/gems/ruby-2.5.0/gems/fixture_builder-0.5.1/lib/fixture_builder/configuration.rb:34:in `factory'

jackkinsella avatar Jul 24 '18 12:07 jackkinsella

Ahh.. I think I am running into this issue with the audited gem. Because the table class is Audited::Audit, it seems to not be serializing the JSONB fields correctly and instead stores the fields as strings, which breaks my specs unfortunately. I guess I can just not test reading the audit logs, but it's a bit unfortunate...

Hmm, based on the issue, I think a hacky workaround might be to just add define the un-namespaced class somewhere appropriate to get FixtureBuilder to find the right class. I put it in my fixture builder block and it seems to resolve the issue without affecting other places. Though this may not be possible if the un-namespaced class already exists. But e.g.

Audit = Audited::Audit

ibrahima avatar Apr 05 '22 22:04 ibrahima

@jackkinsella @ibrahima As anyone who knows me will attest I'm a fan of namespaces, so I've run into this issue a number of times. The problem, as you've no doubt determined, is FixtureBuilder trying to determine the class from the table name. In the example of the Audited gem (which I also use and quite like), the table name is audits; applying the line of code that @jackkinsella identified we end up with:

  table_klass = table_name.classify.constantize rescue nil
  # "audits".classify => "Audit"
  # "Audit".contantize => *BOOM* since Audit is not a top-level constant
  # rescue nil => nil

I've worked around it by adding an explicit configure_tables block, in which you can set the class that should be associated with a given table, as well as what file to store the YAML in. For example:

  builder.factory do
    builder.configure_tables(
      audits: { class: "Audited::Audit", file: 'audited/audits' }
    )
  end

I hope to merge this functionality into the gem (I've spoken with the maintainers, and they're amendable; I just haven't gotten around to it, so the delay is entirely my fault), but in the meantime I've been using my fork for the past year or so without any problems.

I hope this helps.

amilligan avatar Aug 27 '23 16:08 amilligan