【问题标题】:How to insert data in join table based on HABTM association rails 4如何基于HABTM关联rails 4在连接表中插入数据
【发布时间】:2016-08-27 11:05:31
【问题描述】:

我在炼油厂 cms 中创建了一个 HABTM 关联,​​但它返回如下错误:

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

这是我的 restaurant.rb 模型:

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

这是我的 wine.rb 模型:

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

这是我的连接表模型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

这里是 restaurants_controller.rb 控制器:

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

这里是餐厅_form.html.erb表格:

<%= 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 -%>

这是迁移文件:

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

当我发布我的表单时,它没有执行任何调用连接表的操作。

如果我尝试在rails console 上运行以下命令,它会返回以下错误:

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>'

所有迁移都已运行,也没有迁移或种子待定。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-4 has-and-belongs-to-many model-associations refinerycms


    【解决方案1】:

    如果您使用 form_for,您可以在您的视图 app/views/restaurants/_form 中使用此波纹管

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

    不要在你的控制器中忘记这个

     params.require(:restaurant).permit(:name, :wine_ids => [])
    

    【讨论】:

    • 它说:uninitialized constant Refinery::Georgiantoast::Restaurant::RestaurantsWine 这也是我的餐厅控制器新方法def new @wines = Refinery::Georgiantoast::Wine.all end 我在餐厅控制器中写了它访问@wines的新方法
    • 在 Rails 控制台中它可以工作吗? 'Restaurant.first.wines.new'
    • 我试过了:Refinery::Georgiantoast::Restaurant.first.wines.new 它说:NameError: uninitialized constant Refinery::Georgiantoast::Restaurant::RestaurantsWine
    【解决方案2】:

    您似乎在 Wine 和 Restaurant 课程中有错字。关系应该是通过restaurant_wines 而不是restaurants_wines(所以只有“wine”应该是复数)。

    如果您尚未将wine_idrestaurant_id 列添加到连接表,则需要这样做。一旦他们在那里,你应该是

    【讨论】:

    • 非常感谢您的识别,以及如何在 Rails 控制台中访问它?是的,我在连接表中添加了wine_idrestaurant_id,命名为:restaurants_wines 是表名是好的restaurants_wines?
    • 我试过了:Refinery::Georgiantoast::Restaurant.first.wines.new 它说:NameError: uninitialized constant Refinery::Georgiantoast::Restaurant::RestaurantsWine
    • 您似乎仍然在应用程序中的某处指代不正确的拼写。您是否在 Restaurant 模型中的两个 has_many 关系中明确更改了 restaurant_wines 的拼写?如果是这样,您是否尝试过重新启动 Rails 控制台或服务器?除此之外,我认为您尝试创建记录的方式应该可行。
    • 如果我这样做:Refinery::Georgiantoast::Restaurant.first.wines.new 它会说这样的错误:ActiveRecord::StatementInvalid: PG::UndefinedTable: ERROR: relation "refinery_georgiantoast_restaurant_wines" does not exist
    • 餐厅模式或葡萄酒模式也需要更改?我已经改变了两种模型。你能解释一下吗?我们需要改变一种餐厅模式吗?
    【解决方案3】:

    我知道这是一个老问题,但我遇到了一些我认为类似的问题,所以我会留下我的答案,以防它对某人有所帮助。

    我相信在您迁移连接表时,您正在创建一个restaurants_wines 表,但炼油厂希望它被称为refinery_restaurants_wine,或者,从您的错误看来,refinery_georgiantoast_restaurants_wine。改成

    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
    

    应该可以解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-03-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-04-14
      相关资源
      最近更新 更多