Rails 通过与附加属性关联形成 has_many 吗?

发布于 2024-12-19 07:10:55 字数 1353 浏览 4 评论 0原文

如何为具有附加属性的 has_many :through 关联生成表单字段?

has_many :through 关系有一个名为 weight 的附加列。

这是连接表的迁移文件:

create_table :users_widgets do |t|
  t.integer :user_id
  t.integer :widget_id
  t.integer :weight

  t.timestamps
end

模型如下所示:

User
  has_many :widgets, :through => :users_widgets,
           :class_name => 'Widget',
           :source => :widget
  has_many :users_widgets
  accepts_nested_attributes_for :widgets # not sure if this is necessary


Widget
  has_many :users, :through => :users_widgets,
           :class_name => 'User',
           :source => :user
  has_many :users_widgets
  accepts_nested_attributes_for :users # not sure if this is necessary


UsersWidget
  belongs_to :user
  belongs_to :widget

为了简单起见,Widget 和 User 只有一个名为 name 的字段,因此 User.first.nameWidget.first.name

问题:

  • 如何将具有相应权重的窗口小部件的下拉选择附加到用户创建/编辑表单?

  • 如何动态地将其他小部件表单添加到用户或将用户表单添加到小部件以轻松添加或删除这些关系? nested_form_for gem 似乎是完美的解决方案,但我一直无法让它工作。

  • 除了模型和表单部分之外,我的控制器还需要进行任何更改吗?


快速说明..我对在用户表单中创建新的小部件或在小部件表单中创建新用户不感兴趣,我只希望能够从现有对象中进行选择。

我正在运行 Rails 3.1 和 simple_form 2.0.0dev 来生成我的表单。

How can I generate form fields for a has_many :through association that has additional attributes?

The has_many :through relationship has an additional column called weight.

Here's the migration file for the join table:

create_table :users_widgets do |t|
  t.integer :user_id
  t.integer :widget_id
  t.integer :weight

  t.timestamps
end

The models look like this:

User
  has_many :widgets, :through => :users_widgets,
           :class_name => 'Widget',
           :source => :widget
  has_many :users_widgets
  accepts_nested_attributes_for :widgets # not sure if this is necessary


Widget
  has_many :users, :through => :users_widgets,
           :class_name => 'User',
           :source => :user
  has_many :users_widgets
  accepts_nested_attributes_for :users # not sure if this is necessary


UsersWidget
  belongs_to :user
  belongs_to :widget

For the sake of simplicity, Widget and User only have one field of their own called name, ergo User.first.name and Widget.first.name

Questions:

  • How would I append a dropdown selection for Widgets with the corresponding weight to the User create/edit form?

  • How can I dynamically add additional Widget forms to Users or User forms to Widgets to easily add or remove these relationships? The nested_form_for gem seems to be the perfect solution but I haven't been able to get it working.

  • Apart from the models and the form partials, are there any changes that need to be made to my controller?


Quick note.. I'm not interested in creating new Widgets in the User form or new Users in the Widget form, I only want the ability to select from existing objects.

I'm running Rails 3.1 and simple_form 2.0.0dev for generating my forms.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

み格子的夏天 2024-12-26 07:10:55

我将使用 cocoon 来解决您的问题,这是我创建的用于处理动态嵌套表单的 gem。我还有示例项目来展示不同类型关系的示例。

你的并没有从字面上包括在内,但从中得出并不难。在您的模型中,您应该编写:

class User 
  has_many :users_widgets
  has_many :widgets, :through -> :user_widgets

  accepts_nested_attributes_for :user_widgets, :reject_if => :all_blank, :allow_destroy => true

  #...
end

然后您需要创建一个部分视图,其中将列出链接的UserWidgets。将此部分放入名为 users/_user_widget_fields.html.haml 的文件中:

.nested-fields
  = f.association :widget, :collection => Widget.all, :prompt => 'Choose an existing widget'
  = f.input :weight, :hint => 'The weight will determine the order of the widgets'
  = link_to_remove_association "remove tag", f

然后在您的 users/edit.html.haml 中编写:

= simple_form_for @user do |f|
  = f.input :name

  = f.simple_fields_for :user_widgets do |user_widget|
    = render 'user_widget_fields', :f => user_widget
  .links
    = link_to_add_association 'add widget', f, :user_widgets

希望这会有所帮助。

I will be solving your problem using cocoon, a gem I created to handle dynamically nested forms. I also have an example project to show examples of different types of relationships.

Yours is not literally included, but is not that hard to derive from it. In your model you should write:

class User 
  has_many :users_widgets
  has_many :widgets, :through -> :user_widgets

  accepts_nested_attributes_for :user_widgets, :reject_if => :all_blank, :allow_destroy => true

  #...
end

Then you need to create a partial view which will list your linked UserWidgets. Place this partial in a file called users/_user_widget_fields.html.haml:

.nested-fields
  = f.association :widget, :collection => Widget.all, :prompt => 'Choose an existing widget'
  = f.input :weight, :hint => 'The weight will determine the order of the widgets'
  = link_to_remove_association "remove tag", f

In your users/edit.html.haml you can then write:

= simple_form_for @user do |f|
  = f.input :name

  = f.simple_fields_for :user_widgets do |user_widget|
    = render 'user_widget_fields', :f => user_widget
  .links
    = link_to_add_association 'add widget', f, :user_widgets

Hope this helps.

愛上了 2024-12-26 07:10:55

根据你的问题。我做了一个简单的应用程序。
来源在这里:https://github.com/yakjuly/nest_form_example
我将其部署到heroku,您可以打开页面:http://glowing-lightning-1954。 heroku.com/users/new

答案

  1. 你希望用户表单可以选择带有权重的小部件,需要做更多工作。下拉选择不能满足你的要求。

  2. 我在“bootstrap-rails”插件中混合“nested_form”,您可以更轻松地添加nested_fields

  3. 在我的示例中,您需要添加一个调用 select 的操作,并使 WidgetsController#create 可以 responsed_with :js

代码是基于simple_form的,你可以尝试一下。

base your question. I made a simple App.
source is here: https://github.com/yakjuly/nest_form_example
I deployed it to heroku, you can open page: http://glowing-lightning-1954.heroku.com/users/new

answers

  1. you want user form can select widget with weight, need do more work.dropdown selection can not satisfy your requirement.

  2. I mix "nested_form" in a "bootstrap-rails" plugin, you can add the nested_fields easier

  3. in my example, you need add a action calls select, and make WidgetsController#create can responsed_with :js

the code is based simple_form, you can have a try.

溺深海 2024-12-26 07:10:55

非常感谢 cocoon 指针 nathanvda。当我尝试在 Rails 4.0.0-rc1 下实现此功能时,我一直对遇到的一些问题摸不着头脑,我想我会分享我的发现,以防万一有人在尝试此 udner Rails4 时遇到相同的问题。

以上面的代码为例,我将 user_id 和 widget_id 添加到允许的参数中,因为它们保存在连接表 user_widgets 中。在rails 3中,您必须将它们添加到用户模型中的attr_accesible中,但在rails 4中,您必须将它们添加到用于嵌套的主模型的控制器中允许的参数中,所以这里将是users_controller

params.require(:user).permit(...user_fields...,  
  user_widgets_attributes: [:user_id, :widget_id])

:这最终会带来几个问题:

  1. 更新用户记录时,每个关联(小部件)都会成倍增加。更新和保存记录时,1 变为 2、4、8 等。
  2. 删除关联不起作用,字段会从表单中删除,但关联仍保留在数据库中。

要解决这些问题,您还需要将 :id 和 :_destroy 添加到允许的属性列表中:

params.require(:user).permit(...user_fields...,  
  user_widgets_attributes: [:user_id, :widget_id, :id, :_destroy])

之后它就可以完美地工作。

Juergen

PS:现在您必须使用 Gemfile 中的 git 存储库才能在 Rails 4 下使用 Cocoon,直到发布兼容 Rails 4 的 gem。感谢 nathanvda 关于我的错误报告的电子邮件!

Thanks a lot for the cocoon pointer nathanvda. I have been scratching my head about some problems I had when trying to implement this under rails 4.0.0-rc1 and I thought I would share my findings just in case someone has the same problems when attempting this udner rails4.

Using the above code as an example, I did add user_id and widget_id to the permitted parameters as they are saved in the connecting table user_widgets. In rails 3 you did have to add them to attr_accesible in the user model but in rails 4 you have to add them to the allowed parameters in the controller of the main model you use for nesting, so here that would be the users_controller:

params.require(:user).permit(...user_fields...,  
  user_widgets_attributes: [:user_id, :widget_id])

Doing only this you end up with several of problems:

  1. Every association (widget) gets multiplied when updating a user record. 1 becomes 2, 4, 8, and so on, when updating and saving the record.
  2. removing an association does not work, the field is removed from the form but the association remains in the DB.

To fix these problems you also need to add :id and :_destroy to the list of permitted attributes:

params.require(:user).permit(...user_fields...,  
  user_widgets_attributes: [:user_id, :widget_id, :id, :_destroy])

after that it works flawlessly.

Juergen

PS: For now you have to use the git repository in your Gemfile to use cocoon under rails 4 until a rails 4 compatible gem is released. Thanks for the email nathanvda on my bug report!!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文