用户,表单和任务关联rails

时间:2016-04-08 13:07:01

标签: ruby-on-rails task model-associations

我有一个应用程序允许用户填写表单(名为“清单”),然后有一个他将要做的任务列表。任务(名为“建议”)与用户在表单中提供的答案相关。 例如,如果一个问题是“你做过晚餐吗?”并且用户回答“否”,然后将显示建议“去做饭”。

完成建议后,用户可将其标记为已完成。所有用户的建议都是一样的。它们已由管理员在应用程序中创建。

因此用户有一个清单,清单属于用户。

我遇到的问题是:当用户将建议标记为已完成时,会将所有用户标记为已完成。那不应该。

我不确定如何解决这个问题。由于用户没有创建建议,因此建议和用户之间的“Has-many”和“Belongs_to”关联不起作用?

我是铁杆新手,所以如果有人可以提供帮助,我会很高兴。 请注意,我使用Devise来管理用户。

架构:

ActiveRecord::Schema.define(version: 20160407143608) do

  create_table "advices", force: :cascade do |t|
    t.string   "name"
    t.text     "content"
    t.datetime "created_at",  null: false
    t.datetime "updated_at",  null: false
    t.integer  "category_id"
    t.boolean  "status"
    t.string   "linkname1"
    t.text     "link1"
    t.text     "link2"
    t.string   "linkname2"
    t.text     "link3"
    t.string   "linkname3"
    t.integer  "ref"
    t.boolean  "completed"
  end

  create_table "categories", force: :cascade do |t|
    t.string   "name",       null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "checklists", force: :cascade do |t|
    t.boolean  "facebook"
    t.boolean  "twitter"
    t.boolean  "linkedin"
    t.boolean  "viadeo"
    t.boolean  "instagram"
    t.boolean  "community"
    t.boolean  "cms"
    t.boolean  "seo"
    t.boolean  "crowdfunding"
    t.datetime "created_at",   null: false
    t.datetime "updated_at",   null: false
    t.integer  "user_id"
  end

  add_index "checklists", ["user_id"], name: "index_checklists_on_user_id"

  create_table "users", force: :cascade do |t|
    t.string   "email",                  default: "", null: false
    t.string   "encrypted_password",     default: "", null: false
    t.string   "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer  "sign_in_count",          default: 0,  null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.string   "current_sign_in_ip"
    t.string   "last_sign_in_ip"
    t.datetime "created_at",                          null: false
    t.datetime "updated_at",                          null: false
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true
  add_index "users", ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true

end

模特:

class Advice < ActiveRecord::Base
    belongs_to :category
end

class Checklist < ActiveRecord::Base
    belongs_to :user
end

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
  has_many :checklists
end

查看:

<%= advice.name %> | <%= link_to "Completed", complete_advices_path(advice), method: :put %>

控制器:

  def complete
   @advice.completed = true
   @advice.save
   redirect_to root_path
  end

1 个答案:

答案 0 :(得分:1)

您需要一个联接模型。

$ rails g model UserAdvice user:references advice:references

class UserAdvice
   belongs_to :user
   belongs_to :advice
end

在user.rb

has_many :user_advices
has_many :advices, through: :user_advices
在advice.rb中

has_many :user_advices
has_many :users, through: :user_advices 

在检查某些内容时在连接模型中创建一条记录,然后查询该表以确保为单个用户完成任务。

因此,当用户检查任务并提交而不是使用completed布尔值时,您实际上会创建一个包含advice_iduser_id的记录。然后,如果该建议存在该记录,则应该为该用户检查该记录。这有意义吗?

例如,如果您从已完成任务的用户那里隐藏已完成的任务,则可以说

<% if UserAdvice.where(user_id: current_user.id, advice_id: advice.id).count > 0 %>

这会起作用,一开始就很好,但这样做可能会减慢你的应用程序速度。如果有很多建议,你可能想要做的就是运行一次查询并获取所有user_advice记录并拔出id。然后针对单个记录检查该数组的ID。

在您的控制器中

 # this will return an array of advice_ids
 @user_advices = UserAdvice.where(user_id: current_user).pluck(:advice_id)  

然后,当您在视图中遍历建议时:

<% unless @user_advices.include?(advice.id) %>
  show the advice
<% end %>

编辑:

要在完整操作中创建记录:

def complete
  UserAdvice.create(user_id: current_user.id, advice_id: @advice.id)
  redirect_to root_path
end