【问题标题】:How to setup basic Rails models associations?如何设置基本的 Rails 模型关联?
【发布时间】:2018-11-25 18:52:20
【问题描述】:

大家好,我正在开发一个设计用户注册并登录的应用程序,一旦用户登录,他们就可以“创建团队”或“加入团队”。我的协会是这样设置的

user.rb

class User < ApplicationRecord
   devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :validatable, :confirmable 
   validates_presence_of :phone, :city, :state, :street, :zip, presence: true, on: :create

   belongs_to :team      
end

team.rb

class Team < ApplicationRecord
   has_many :users   
end

我的桌子已经布置好了

schema.rb

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

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.datetime "created_at", null: false
  t.datetime "updated_at", null: false
  t.string "confirmation_token"
  t.datetime "confirmed_at"
  t.datetime "confirmation_sent_at"
  t.string "firstname"
  t.integer "team_id"
  t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
  t.index ["email"], name: "index_users_on_email", unique: true
  t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
end

team_controller.rb

class TeamController < ApplicationController
   before_action :authenticate_user!

   def index
     @team = current_user.team
   end

   def new_team

   end

   def create_team
     @team = current_user.create_team(sanitize_team)
     if @team.save 
       redirect_to team_root_path
     else
       render json: @team.errors.full_messages
     end
   end

   def join_team 
     @teams = Team.all
   end

   def team

   end

   private 

   def sanitize_team
     params.require(:team).permit(:team_name, :team_statement)
   end
end

我希望用户的“team_id”属性在创建团队时使用团队 ID 进行更新。或者当他们加入团队时。我的联想正确吗?我将如何在控制器中实现这一点?

【问题讨论】:

  • 您的路线是什么样的?您是否使用 Rail 的默认 RESTful 路由(即您的 routes.rb 文件中的 resources :teams?不需要创建诸如 new_team、create_team 等操作。相反,团队将由控制器的名称暗示,您应该简单地拥有新建、创建等操作。

标签: ruby-on-rails ruby


【解决方案1】:

是的,关联是正确的。只有在数据库模式中添加外键才能做得更好。可以通过生成器rails g migration AddTeamToUsers team:references来完成

有关协会的更多信息可以在这里找到:https://guides.rubyonrails.org/association_basics.html

在控制器中,您只需更改白名单参数以允许team_id。您可能需要在表单中添加如下内容: <%= f.select :team_id, Team.all.map { |t| [t.team_name, t.id] } %>

【讨论】:

  • @DonPaulid 感谢当前当我以用户身份创建团队时的快速回复,team_id 列未使用其所属的正确团队 ID 进行更新。但记录保存在数据库中。
  • @kevinlopez 尝试添加validates :team_id, :team, presence: true。也许它会帮助你。 Team_id 验证数字的存在, :team 验证数据库中团队的存在。
【解决方案2】:

让我们将您的代码示例精简到所需的最低限度:

# app/models/team.rb
class Team < ApplicationRecord
  has_many :users
end

# app/models/user.rb
class User < ApplicationRecord
  belongs_to :team
end

# db/migrate/20181124230131_create_teams.rb
class CreateTeams < ActiveRecord::Migration[5.2]
  def change
    create_table :teams do |t|
      t.string :team_name
      t.timestamps
    end
  end
end

# db/migrate/20181124230136_create_users.rb
class CreateUsers < ActiveRecord::Migration[5.2]
  def change
    create_table :users do |t|
      t.belongs_to :team
      t.timestamps
    end
  end
end

然后在你的控制器中:

team = Team.where(team_name: 'foo').first_or_create!
team.users << current_user

【讨论】:

  • 我的表已经制作好了,但是当我以用户身份创建团队时,我的用户表上的团队 ID 没有更新,并且我已经添加了“team_id”列
  • 我将在上面的代码中包含我的控制器
【解决方案3】:

首先将关联设置为可选:

class User < ApplicationController 
  belongs_to :team, optional: true
end

否则用户模型上的验证不会让用户在没有团队的情况下被保存。

然后设置团队资源:

# config/routes.rb
resources :teams do
  post :join
end

post :join 创建一个额外的POST /teams/:team_id/join 路由。

然后设置控制器:

class TeamsController

  # ...

  # GET /teams/new
  def new
    @team = Team.find
  end

  # POST /teams
  def create
    @team = Team.new(team_params)
    if @team.save
      unless current_user.team
        current_user.update(team: @team)
      end
      redirect_to 'somewhere'
    else
      render :new
    end
  end

  # ...

  def join
    @team = Team.find(params[:team_id])
    if current_user.update(team: @team)
      redirect_to @team, notice: 'Team joined'
    else
      redirect_to @team, error: 'Could not join team'
    end
  end

  #

  private
    def team_params
      params.require(:team).permit(:team_name, :team_statement)
    end 
end

请注意,为您的操作名称添加前缀既不需要也不与“Rails 方式”兼容。为列名添加前缀在很大程度上也是多余的。

【讨论】:

    猜你喜欢
    • 2012-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-27
    • 2021-06-19
    • 1970-01-01
    相关资源
    最近更新 更多