has_many:通过Association,NoMethodError(未定义的方法`每个' for"":String)并保存关联

时间:2016-09-20 20:26:49

标签: ruby-on-rails ruby has-many-through nomethoderror

我无法获得has_many:通过协会工作。我是否需要在post_controller的create方法中设置额外的东西,以保存post_category? (代码下方,错误和我的尝试)

我有一个has_many:通过关联post,post_category和连接表分类如下:

邮政模型:

class Post < ApplicationRecord
  has_many :categorizations
  has_many :post_categories, :through => :categorizations
end

Post :: Category Model(使用命名空间以获得更好的项目结构):

class Post::Category < ApplicationRecord
  has_many :categorizations
  has_many :posts, :through => :categorizations
end

分类模型(使用class_name,Post :: Category命名空间的原因):

class Categorization < ApplicationRecord
  belongs_to :post
  belongs_to :post_category, :class_name => 'Post::Category'
end

然后我在视图中选择了我用post_category创建帖子的地方:

<div class="form-group">
  <%= f.label :post_categories, :class => 'control-label', :value => 'Category: ' %>
  <%= f.select :post_categories, options_from_collection_for_select(all_post_categories, :id, :name), {}, {class: 'selectpicker', :'data-live-search' => 'true', required: 'false' } %>
</div>

在posts_controller中,我允许使用:post_categories符号:

def post_params
  params.require(:post).permit(:post_categories)
end

以下是我的协会迁移文件:

class CreateCategorizations < ActiveRecord::Migration[5.0]
  def change
    create_table :categorizations do |t|
      t.integer :post_id
      t.integer :post_category_id

      t.timestamps
    end
    add_index :categorizations, :post_id
    add_index :categorizations, :post_category_id
    # multiple-key index enforces uniqueness on (post_id, post_category_id)
    # pairs, so that a category can't have the same post twice
    add_index :categorizations, [:post_id, :post_category_id], unique: true
  end
end

当我尝试提交表单时,我在日志中收到以下错误:

NoMethodError (undefined method `each' for "3":String):
app/controllers/posts_controller.rb:32:in `create'

所以我搜索了一些好的答案 - &gt; You can't assign string to association

我尝试了另一种方法让这种关联发挥作用。

所以我尝试使用post_category_id,就像推荐的here

一样

我在视图的选择中设置了

<%= f.select :post_category_id, options_from_collection_for_select(all_post_categories, :id, :name), {}, {class: 'selectpicker', :'data-live-search' => 'true', required: 'false' } %>

然后在posts_controller中允许category_id:

def post_params
  params.require(:post).permit(:post_category_id)
end

并在Post模型中:

class Post < ApplicationRecord
  has_many :categorizations
  has_many :post_category_id, :through => :categorizations
end

这是新错误:

Could not find the source association(s) "post_category_id" or :post_category_id in model Categorization. Try 'has_many :post_category_id, :through => :categorizations, :source => <name>'. Is it one of post or post_category?

好的,因为没有post_category_id关联。

更新

post_params:

<ActionController::Parameters {"content"=>"content", "post_categories"=>"2"} permitted: true>

2 个答案:

答案 0 :(得分:1)

我通过此answer和此question为我找到了正确的解决方案。

第一个解决方案只保存一个Post :: Category with Post

关于这个answer,我不得不将posts_controller中的permit参数更改为:

def post_params
  params.require(:post).permit(:post_category_ids)
end

然后我还需要更改视图中的选择,我在其中创建一个带有post_category的帖子:

<div class="form-group">
  <%= f.label :post_category_ids, :class => 'control-label', :value => 'Category: ' %>
  <%= f.select :post_category_ids, options_from_collection_for_select(all_post_categories, :id, :name), {}, {class: 'selectpicker', :'data-live-search' => 'true', required: 'false' } %>
</div>

那就是它。其余的代码仍然与我在第二次尝试之前展示的相同。

使用帖子保存多个Post :: Category的第二个解决方案

关于这个question,我需要将posts_controller中的permit参数更改为:

def post_params
  params.require(:post).permit(:post_category_ids => [])
end

要同时选择多个Post :: Category,我需要在视图中的select中添加multiple: 'true'

<div class="form-group">
  <%= f.label :post_category_ids, :class => 'control-label', :value => 'Category: ' %>
  <%= f.select :post_category_ids, options_from_collection_for_select(all_post_categories, :id, :name), {}, {class: 'selectpicker', :'data-live-search' => 'true', required: 'false', multiple: 'true' } %>
</div>

答案 1 :(得分:0)

我认为你需要改变这个:

<%= f.select :post_categories, options_from_collection_for_select(all_post_categories, :id, :name), {}, {class: 'selectpicker', :'data-live-search' => 'true', required: 'false' } %>

到此:

  <%= f.select :post_categories[:id],
  options_from_collection_for_select(all_post_categories, :id, :name), 
  class: 'selectpicker', :'data-live-search' => 'true', required: 'false' , include_hidden: false} %>

如果我错了,请拍我。

根据SO 4585355

编辑:包含hidden:false for rails 4.2+