基于Ryan Bates出色的RailsCast#258,我遇到了问题。
情况如下:
class User < ActiveRecord::Base
has_many :capabilities,
:dependent => :destroy
has_many :skills, :through => :capabilities,
:uniq => true
has_many :raters,
:through => :capabilities,
:foreign_key => :rater_id,
:uniq => true
attr_accessible :name, :skill_tokens
attr_reader :skill_tokens
def skill_tokens=(tokens)
self.skill_ids = Skill.ids_from_tokens(tokens)
end
end
class Capability < ActiveRecord::Base
belongs_to :user
belongs_to :rater, class_name: "User"
belongs_to :skill
validates_uniqueness_of :rater_id, :scope => [:user_id, :skill_id]
end
class Skill < ActiveRecord::Base
has_many :capabilities
has_many :users, :through => :capabilities,
:uniq => true
has_many :raters, :through => :capabilities,
:foreign_key => :rater_id
end
表单包含技能标记的普通文本字段,它们作为ID传递:
.field
= f.label :skill_tokens, "Skills"
= f.text_field :skill_tokens, data: {load: @user.skills}
因此,用户可以通过功能获得许多技能。在分配技能时,还应在能力模型中跟踪评估者。
使用Ryans jquery TokenInput示例我创建了一个适当的表单,允许用户使用tokenInput文本字段分配(和创建)技能。
问题在于处理数据并在保存关联之前设置评估者。
通过一些ruby魔法,用户模型上的self.skill_ids设置用于创建关联模型的id,因此控制器操作非常简单:
def update
@user = User.find(params[:id])
respond_to do |format|
if @user.update_attributes(params[:user])
format.html { redirect_to @user, notice: 'User was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @user.errors, status: :unprocessable_entity }
end
end
end
显然,如果我想在功能模型上设置额外的rater属性,那么使用update_attributes就不会那么容易。
那么我怎样才能通过“轨道方式”实现这一目标 - 编写漂亮,可读的代码? 非常感谢任何帮助!
答案 0 :(得分:0)
您如何设置rater_id
?
如果您计划为用户在表单上添加的每项技能接受评估者的用户输入, 我无法看到你将如何使用基于令牌输入的输入字段来实现这一目标。您将不得不选择其他类型的输入。
如果您计划将评估者设置为当前登录的用户,或者根据其他一些业务逻辑设置评估者,我的方法是覆盖skill_ids=
方法中的#user.rb
attr_accessor :current_rater
def skill_ids=(ids)
return false if current_rater.nil? || User.find_by_id(current_rater).nil?
capabilities.where("skill_id not in (?)", ids).destroy_all
ids.each do |skill_id|
capabilities.create(:skill_id => skill_id, :rater_id => self.current_rater) if capabilities.find_by_id(skill_id).nil?
end
end
#users_controller.rb
def update
@user = User.find(params[:id])
#Replace 'current_user' with whatever method you are using to track the logged in user
params[:user].merge(:current_rater => current_user)
respond_to do |format|
...
end
end
方法。用户模型可以按您的需要工作,添加attr_accessor来存储current_rater并从控制器传递current_rate。
类似的东西:
{{1}}
可能不如你所希望的那么优雅,但它应该能够胜任这个工作吗?