cldwalker / hirb

A mini view framework for console/irb that's easy to use, even while under its influence. Console goodies include a no-wrap table, auto-pager, tree and menu.
http://tagaholic.me/hirb/
MIT License
1.65k stars 72 forks source link

"Hirb Error: missing attribute:" when using custom ActiveRecord select statements and hirb.yml #93

Open redbar0n opened 9 years ago

redbar0n commented 9 years ago

A custom ActiveRecord select statement like

BlogEntry.select(:title,:url).group(:title,:url).having("count(*) > 1")

works fine without Hirb:

irb(main):060:0> Hirb.disable
=> false
irb(main):061:0> BlogEntry.select(:title,:url).group(:title,:url).having("count(*) > 1")
D, [2015-07-08T13:06:40.873613 #3] DEBUG -- :   BlogEntry Load (6.7ms)  SELECT "blog_entries"."title", "blog_entries"."url" FROM "blog_entries" GROUP BY "blog_entries"."title", "blog_entries"."url" HAVING count(*) > 1
=> #<ActiveRecord::Relation [#<BlogEntry id: nil, url:  ...   ]>

But when Hirb is enabled, and using hirb.yml, it will give an (unnecessary) missing attribute error. I say unnecessary because when I have specifically specified in the select statement the fields I'm interested in, I don't want the Hirb.yml definition (which I use as my default) to come back to bite me, like this:

irb(main):062:0> Hirb.enable
=> true
irb(main):063:0> BlogEntry.select(:title,:url).group(:title,:url).having("count(*) > 1")
D, [2015-07-08T13:06:48.941044 #3] DEBUG -- :   BlogEntry Load (5.3ms)  SELECT "blog_entries"."title", "blog_entries"."url" FROM "blog_entries" GROUP BY "blog_entries"."title", "blog_entries"."url" HAVING count(*) > 1
Hirb Error: missing attribute: blog_id
    /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.2/lib/active_record/attribute_methods/read.rb:93:in `block in _read_attribute'
    /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.2/lib/active_record/attribute_set.rb:31:in `block in fetch_value'
    /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.2/lib/active_record/attribute.rb:150:in `value'
    /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.2/lib/active_record/attribute_set.rb:31:in `fetch_value'
    /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.2/lib/active_record/attribute_methods/read.rb:93:in `_read_attribute'
    /app/vendor/bundle/ruby/2.0.0/gems/activerecord-4.2.2/lib/active_record/attribute_methods.rb:50:in `__temp__26c6f676f59646'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/helpers/object_table.rb:10:in `block (2 levels) in render'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/helpers/object_table.rb:10:in `each'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/helpers/object_table.rb:10:in `inject'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/helpers/object_table.rb:10:in `block in render'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/helpers/object_table.rb:9:in `each'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/helpers/object_table.rb:9:in `inject'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/helpers/object_table.rb:9:in `render'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/helpers/auto_table.rb:22:in `render'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/formatter.rb:73:in `_format_output'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/formatter.rb:56:in `format_output'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/view.rb:205:in `render_output'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/view.rb:123:in `view_output'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/view.rb:201:in `view_or_page_output'
    /app/vendor/bundle/ruby/2.0.0/gems/hirb-0.7.3/lib/hirb/view.rb:187:in `output_value'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb.rb:493:in `block (2 levels) in eval_input'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb.rb:624:in `signal_status'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb.rb:489:in `block in eval_input'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb/ruby-lex.rb:247:in `block (2 levels) in each_top_level_statement'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb/ruby-lex.rb:233:in `loop'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb/ruby-lex.rb:233:in `block in each_top_level_statement'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb/ruby-lex.rb:232:in `catch'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb/ruby-lex.rb:232:in `each_top_level_statement'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb.rb:488:in `eval_input'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb.rb:397:in `block in start'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb.rb:396:in `catch'
    /app/vendor/ruby-2.0.0/lib/ruby/2.0.0/irb.rb:396:in `start'
    /app/vendor/bundle/ruby/2.0.0/gems/railties-4.2.2/lib/rails/commands/console.rb:110:in `start'
    /app/vendor/bundle/ruby/2.0.0/gems/railties-4.2.2/lib/rails/commands/console.rb:9:in `start'
    /app/vendor/bundle/ruby/2.0.0/gems/railties-4.2.2/lib/rails/commands/commands_tasks.rb:68:in `console'
    /app/vendor/bundle/ruby/2.0.0/gems/railties-4.2.2/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    /app/vendor/bundle/ruby/2.0.0/gems/railties-4.2.2/lib/rails/commands.rb:17:in `<top (required)>'
    /app/bin/rails:4:in `require'
    /app/bin/rails:4:in `<main>'
irb(main):064:0> 

Probably due to the way Hirb hard-enforces the hirb.yml.

My Hirb.yml file looks something like this:

:output:
  BlogEntry:
    :options:
      :fields:
        - id
        - title
        - url
        - blog_id
        - read_counter
        - description
        - content
        - created_at
        - updated_at

Could you make it not hard-enforce hirb.yml, in case one wants to use custom select statements?

cldwalker commented 9 years ago

Thanks for reporting your issue! This is one of my 4 active issues. Use that link to check how soon your issue will be answered. Don't forget to check your issue against this project's CONTRIBUTING.md. Cheers.

cldwalker commented 9 years ago

Hi. Configuring :fields is meant for required fields. Hirb doesn't have a notion of optional fields and I wouldn't want to make this default. The underlying helper, ObjectTable is pretty tiny. You can extend ObjectTable to support an optional fields mode or write your own helper that allows for optional fields and configure hirb to use it. Let me know if you'd like to extend ObjectTable and I can keep this open

redbar0n commented 9 years ago

I'm not advocating for optional fields, I'm simply suggesting that Hirb should suspend its required fields when the user is explicitly telling ActiveRecord what fields he wants to select. Otherwise, as it is now, it breaks user expectation of the standard ActiveRecord functionality.

What I'm suggesting is that Hirb will ignore requiring all the fields specified by default (in hirb.yml) when the user is using a select statement to explicitly specify the required fields. Otherwise, the table output can work as normal and print the columns in the nice table layout (while simply pertaining to only the fields/columns specified in the select statement).

Doesn't that make sense?

SampsonCrowley commented 7 years ago

This is definitely an issue. Hirb shouldn't require the regular attributes when using a select statement

davegson commented 6 years ago

+1

JonaOnMonday commented 3 years ago

+1