0

I have created a HABTM association in refinery cms but it returns error like below:

ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  relation "refinery_georgiantoast_restaurant_wines" does not exist
LINE 5:                WHERE a.attrelid = '"refinery_georgiantoast_r...
                                          ^
:               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
                FROM pg_attribute a LEFT JOIN pg_attrdef d
                  ON a.attrelid = d.adrelid AND a.attnum = d.adnum
               WHERE a.attrelid = '"refinery_georgiantoast_restaurant_wines"'::regclass
                 AND a.attnum > 0 AND NOT a.attisdropped
               ORDER BY a.attnum

/vendor/extensions/georgiantoasts/app/models/refinery/georgiantoast/restaurant.rb

Here is my restaurant.rb model:

module Refinery
  module Georgiantoast
    class Restaurant < Refinery::Core::BaseModel

      validates :title, :presence => true, :uniqueness => true

      belongs_to :avatars, :class_name => '::Refinery::Image'

      has_many :restaurants_wines

      has_many :wines, :through => :restaurants_wines

      # To enable admin searching, add acts_as_indexed on searchable fields, for example:
      #
      #   acts_as_indexed :fields => [:title]

    end
  end
end

/vendor/extensions/georgiantoasts/app/models/refinery/georgiantoast/wine.rb

Here is my wine.rb model:

module Refinery
  module Georgiantoast
    class Wine < Refinery::Core::BaseModel

      validates :title, :presence => true, :uniqueness => true

      belongs_to :avatars, :class_name => '::Refinery::Image'

      has_many :restaurants_wines

      has_many :restaurants, :through => :restaurants_wines

      # To enable admin searching, add acts_as_indexed on searchable fields, for example:
      #
      #   acts_as_indexed :fields => [:title]

    end
  end
end

/vendor/extensions/georgiantoasts/app/models/refinery/georgiantoast/restaurant_wines.rb

Here is my join table model restaurant_wines.rb

module Refinery
  module Georgiantoast
    class RestaurantWine < Refinery::Core::BaseModel

      belongs_to :wine

      belongs_to :restaurant

      # To enable admin searching, add acts_as_indexed on searchable fields, for example:
      #
      #   acts_as_indexed :fields => [:title]

    end
  end
end

/vendor/extensions/georgiantoasts/app/controllers/refinery/georgiantoast/admin/restaurants_controller.rb

Here is restaurants_controller.rb controller:

module Refinery
  module Georgiantoast
    module Admin
      class RestaurantsController < ::Refinery::AdminController

        crudify :'refinery/georgiantoast/restaurant'

        private

        # Only allow a trusted parameter "white list" through.
        def restaurant_params
          params.require(:restaurant).permit(:title, :description, :address, :town, :state, :lat, :lng, :avatars_id, :wine_ids => [])
        end
      end
    end
  end
end

/vendor/extensions/georgiantoasts/app/views/refinery/georgiantoast/admin/restaurants/_form.html.erb

Here is Restaurant _form.html.erb form:

<%= form_for [refinery, :georgiantoast_admin, @restaurant] do |f| -%>
    <%= render '/refinery/admin/error_messages',
               :object => @restaurant,
               :include_object_name => true %>

    <div class='field'>
      <%= f.label :title -%>
      <%= f.text_field :title, :class => 'larger widest' -%>
    </div>

    <div class='field'>
      <%= render '/refinery/admin/wysiwyg',
                 :f => f,
                 :fields => [:description],
                 :object => "georgiantoast/restaurant" -%>
    </div>

    <div class='field'>
      <%= f.label :address -%>
      <%= f.text_field :address -%>
    </div>

    <div class='field'>
      <%= f.label :wine -%>
      <%= select_tag "#{f.object_name}[wine_ids][]", options_for_select(Refinery::Georgiantoast::Wine.all.collect { |wine| [wine.title, wine.id] }), {multiple: true} -%>
    </div>


    <%= render '/refinery/admin/form_actions', :f => f,
               :continue_editing => false,
               :delete_title => t('delete', :scope => 'refinery.restaurants.admin.restaurants.restaurant'),
               :delete_confirmation => t('message', :scope => 'refinery.admin.delete', :title => @restaurant.title) -%>
<% end -%>

Here is the migration file:

class CreateJoinTableRestaurantsWines < ActiveRecord::Migration
  def change
    create_join_table :restaurants, :wines do |t|
      t.index :restaurant_id
      t.index :wine_id
    end
  end
end

When I post my form it didn't perform any action of invoking join table.

If I try to run below command on rails console it returns me below error:

2.2.3 :001 > r = Refinery::Georgiantoast::Restaurant.first
  Refinery::Georgiantoast::Restaurant Load (1.0ms)  SELECT  "refinery_georgiantoast_restaurants".* FROM "refinery_georgiantoast_restaurants"  ORDER BY "refinery_georgiantoast_restaurants"."id" ASC LIMIT 1
 => #<Refinery::Georgiantoast::Restaurant id: 1, title: "abc restaurant", description: "<p>abc restaurant</p>", address: "12 helifax estate", town: "helifax", state: "toronto", lat: #<BigDecimal:55fdfc0,'-0.12555555E2',18(27)>, lng: #<BigDecimal:55fde80,'0.74555555E2',18(27)>, avatars_id: 3, position: nil, created_at: "2016-08-27 11:26:29", updated_at: "2016-08-27 11:26:29"> 
2.2.3 :002 > r.wine_ids
ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR:  relation "refinery_georgiantoast_restaurant_wines" does not exist
LINE 5:                WHERE a.attrelid = '"refinery_georgiantoast_r...
                                          ^
:               SELECT a.attname, format_type(a.atttypid, a.atttypmod),
                     pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
                FROM pg_attribute a LEFT JOIN pg_attrdef d
                  ON a.attrelid = d.adrelid AND a.attnum = d.adnum
               WHERE a.attrelid = '"refinery_georgiantoast_restaurant_wines"'::regclass
                 AND a.attnum > 0 AND NOT a.attisdropped
               ORDER BY a.attnum

    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/connection_adapters/postgresql_adapter.rb:592:in `async_exec'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/connection_adapters/postgresql_adapter.rb:592:in `block in exec_no_cache'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:472:in `block in log'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activesupport-4.2.6/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/connection_adapters/abstract_adapter.rb:466:in `log'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/connection_adapters/postgresql_adapter.rb:592:in `exec_no_cache'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/connection_adapters/postgresql_adapter.rb:584:in `execute_and_clear'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/connection_adapters/postgresql/database_statements.rb:160:in `exec_query'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/connection_adapters/postgresql_adapter.rb:733:in `column_definitions'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/connection_adapters/postgresql/schema_statements.rb:197:in `columns'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/connection_adapters/schema_cache.rb:43:in `columns'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/connection_adapters/schema_cache.rb:49:in `columns_hash'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/associations/association_scope.rb:85:in `column_for'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/associations/association_scope.rb:94:in `bind'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/associations/association_scope.rb:103:in `last_chain_scope'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activerecord-4.2.6/lib/active_record/associations/association_scope.rb:139:in `add_constraints'
... 9 levels...
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/railties-4.2.6/lib/rails/commands/console.rb:9:in `start'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/railties-4.2.6/lib/rails/commands/commands_tasks.rb:68:in `console'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/railties-4.2.6/lib/rails/commands/commands_tasks.rb:39:in `run_command!'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/railties-4.2.6/lib/rails/commands.rb:17:in `<top (required)>'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:274:in `require'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:274:in `block in require'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:274:in `require'
    from /home/muhammad/workspace/georgian-toast-wines/bin/rails:9:in `<top (required)>'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:268:in `load'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:268:in `block in load'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:240:in `load_dependency'
    from /home/muhammad/.rvm/gems/ruby-2.2.3@georgian-toast/gems/activesupport-4.2.6/lib/active_support/dependencies.rb:268:in `load'
    from /home/muhammad/.rvm/rubies/ruby-2.2.3/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from /home/muhammad/.rvm/rubies/ruby-2.2.3/lib/ruby/site_ruby/2.2.0/rubygems/core_ext/kernel_require.rb:54:in `require'
    from -e:1:in `<main>'

All migrations has ran, no migration or seed is pending too.

3 Answers3

0

If you use form_for you can use this bellow in your view app/views/restaurants/_form

 <%= f.collection_select :wine_ids, @wines, :id, :name, {}, {:multiple => true} %>

Don't forget this in your controller

 params.require(:restaurant).permit(:name, :wine_ids => [])
Breno Perucchi
  • 873
  • 7
  • 16
  • it says: `uninitialized constant Refinery::Georgiantoast::Restaurant::RestaurantsWine` also this is my restaurant controller new method `def new @wines = Refinery::Georgiantoast::Wine.all end` I wrote it in restaurant controller new method to access `@wines` –  Aug 27 '16 at 12:19
  • In rails console this it work? 'Restaurant.first.wines.new' – Breno Perucchi Aug 27 '16 at 12:20
  • I tried: `Refinery::Georgiantoast::Restaurant.first.wines.new` It says: `NameError: uninitialized constant Refinery::Georgiantoast::Restaurant::RestaurantsWine` –  Aug 27 '16 at 12:24
0

You appear to have a typo in the Wine and Restaurant classes. The relationship should be through restaurant_wines rather than restaurants_wines (so only "wine" should be plural).

You need to add wine_id and restaurant_id columns to the join table if you haven't done so already. Once they're there, you should be

kohrVid
  • 33
  • 2
  • 5
  • Thanks very much for identifying, plus how I can access it in rails console? Yes, I have added `wine_id` and `restaurant_id` in join table named: `restaurants_wines` is table name is fine `restaurants_wines`? –  Aug 27 '16 at 12:38
  • I tried: `Refinery::Georgiantoast::Restaurant.first.wines.new` It says: `NameError: uninitialized constant Refinery::Georgiantoast::Restaurant::RestaurantsWine` –  Aug 27 '16 at 12:42
  • It looks like you're still referring to the incorrect spelling somewhere in your app. Have you definitely changed the spelling of `restaurant_wines` in both of the has_many relationships in your Restaurant model? If so, have you tried perhaps restarting the rails console or server? Apart from that, I think the way you've tried to create the record ought to work. – kohrVid Aug 27 '16 at 13:36
  • If I do: `Refinery::Georgiantoast::Restaurant.first.wines.new` it says error like this: `ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "refinery_georgiantoast_restaurant_wines" does not exist` –  Aug 27 '16 at 13:55
  • It needs to be changed in restaurant model or in wine model as well? i have changed in both models. Could you explain? Do we need to change in one restaurant model? –  Aug 27 '16 at 13:57
  • I've just noticed that the module you used in your example was actually called "Hebel" and not "Georgiantoast" (apologies for missing that earlier - I'm not as familiar with Refinery). Have you tried creating new wines with `Refinery::Hebel::Restaurant.first.wines.new` instead? – kohrVid Aug 27 '16 at 14:08
  • And just to confirm the join table's name should be spelt ":restaurant_wines" wherever it appears in the app (so in both of the has_many relationships in both models). – kohrVid Aug 27 '16 at 14:11
  • The name of my file model file is: `restaurant_wine.rb`. Is that ok? I am still getting same error even after all changes. –  Aug 27 '16 at 17:21
  • The file name for the join table looks fine to me (model file names are typically singular and use snake case). Just to confirm, are you definitely using the correct module names ("Refinery::Hebel") when you attempt to create a new record in the join table? If so, can you confirm that you've run all necessary migrations (`rake db:migrate`)? It _might_ be worth trying to create the record without namespacing (i.e., `Restaurant.first.wines.new`) but, to be honest, I wouldn't expect that to work. – kohrVid Aug 27 '16 at 18:23
  • I have posted question here, could you please just look at the whole question and summary? [https://github.com/refinery/refinerycms/issues/3245](https://github.com/refinery/refinerycms/issues/3245) –  Aug 27 '16 at 23:50
  • It looks like you've generated the join table using `rails g migration` but the [Refinery CMS documentation](http://www.refinerycms.com/guides/relating-resources-in-an-extension) seems to expect something that looks like this --> `rails g refinery:engine restaurant_wines wine_id:integer restaurant_id:integer --extension georgiantoast --namespace georgiantoast`. You may have to delete the join table and generate a new one according to the docs. – kohrVid Aug 28 '16 at 03:33
0

I know this is an old question, but I came across something I think is similar, so I will leave my answer in case it helps someone.

I believe that on your migration for the join table, you are creating a restaurants_wines table, but refinery is expecting it to be called refinery_restaurants_wine, or, as it seems from your error, refinery_georgiantoast_restaurants_wine. Changing it to

class CreateJoinTableRestaurantsWines < ActiveRecord::Migration
  def change
    create_join_table :restaurants, :wines, table_name: "refinery_georgiantoast_restaurants_wine" do |t|
      t.index :restaurant_id
      t.index :wine_id
    end
  end
end

should do the trick.