Man*_*han 5 has-many-through model-associations ruby-on-rails-3
有没有办法避免在分配集合属性时自动保存对象(collection_singular_ids = ids方法)?
例如,我有以下测试和包模型,包有很多测试.用户可以使用多个测试构建包捆绑包.
# test.rb
class Test < ActiveRecord::Base
end
# package.rb
class Package < ActiveRecord::Base
has_many :package_tests
has_many :tests, :through => :package_tests
belongs_to :category
validate :at_most_3_tests
private
# tests count will differ depends on category.
def at_most_3_tests
errors.add(:base, 'This package should have at most three tests') if test_ids.count > 3
end
end
# package_test.rb
class PackageTest < ActiveRecord::Base
belongs_to :package
belongs_to :test
validates_associated :package
end
Run Code Online (Sandbox Code Playgroud)
当包对象是新的时,验证没有问题.
1.9.2 :001> package = Package.new(:name => "sample", :cost => 3.3, :test_ids => [1,2,3,4])
=> #<Package id: nil, name: "sample", cost: 3.3>
1.9.2 :002> package.test_ids
=> [1, 2, 3, 4]
1.9.2 :003> package.save
=> false
1.9.2 :004> package.save!
ActiveRecord::RecordInvalid: Validation failed: This package should have at most three tests
1.9.2: 005> package.test_ids = [1,2]
=> [1, 2]
1.9.2 :005> package.save!
=> true
Run Code Online (Sandbox Code Playgroud)
但是我无法用持久化的包对象来命中at_most_3_tests方法.
在分配测试ID时立即创建连接表记录
1.9.2: 006> package
=> #<Package id: 1, name: "sample", cost: 3.3>
1.9.2: 007> package.test_ids
=> [1,2]
1.9.2: 007> package.test_ids = [1,2,3,4,5]
=> [1,2,3,4,5]
1.9.2: 008> package.test_ids
=> [1,2,3,4,5]
Run Code Online (Sandbox Code Playgroud)
客户端要求是下拉界面,用于选择包形式的多个测试,还使用select2 jquery插件进行下拉.Rhmtl代码看起来像
<%= form_for @package do |f| %>
<%= f.text_field :name %>
<div> <label>Select Tests</label> </div>
<div>
<%= f.select "test_ids", options_for_select(@tests, f.object.test_ids), {}, { "data-validate" => true, :multiple => true} %>
</div>
Run Code Online (Sandbox Code Playgroud)
请帮我解决这个问题.
限制关联数量
您可以使用以下验证,而不是您的方法:
has_many :tests, :length => { :maximum => 3 }
Run Code Online (Sandbox Code Playgroud)
对于使用多重选择
我之前有这个问题,我使用以下代码解决了它:
<%= f.select(:test_ids, options_from_collection_for_select(@tests, :id, :name, @promotion.test_ids), {}, {multiple: true, "data-validate" => true}) =>
Run Code Online (Sandbox Code Playgroud)
我认为options_from_collection_for_select,从这个链接中读取帖子示例的类别可能对您有所帮助.
验证
我使用了validates_associated,如下所示:
validates_associated :tests
Run Code Online (Sandbox Code Playgroud)
用于获取持久对象的旧属性
您可以使用reload进行活动记录,如下所示:
1.9.2: 006> package
=> #<Package id: 1, name: "sample", cost: 3.3>
1.9.2: 007> package.test_ids
=> [1,2]
1.9.2: 007> package.test_ids = [1,2,3,4,5]
=> [1,2,3,4,5]
1.9.2: 007> package.reload
=> #<Package id: 1, name: "sample", cost: 3.3>
1.9.2: 008> package.test_ids
=> [1,2]
Run Code Online (Sandbox Code Playgroud)
或者您可以检查包对象的验证,如果是false则重新加载它:
unless package.valid?
package.reload
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
180 次 |
| 最近记录: |