【问题标题】:Rollback transaction rails console回滚事务导轨控制台
【发布时间】:2017-04-26 18:07:03
【问题描述】:

当我尝试基于用户创建新事件时,我的 rails 控制台出现问题。我有一种感觉,这是我遇到的一个非常简单的错误,但我发帖是因为我不确定应该如何修复它。这是我尝试运行的命令:

user.event = Event.create(:name => "Dummy")

这是我的活动的数据库文件:

class CreateEvents < ActiveRecord::Migration[5.0]
  def change
    create_table :events do |t|
      t.string :name

      t.timestamps
    end
  end
end

这是我的用户数据库文件:

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :name
      t.string :email
      t.string :event
      t.integer :code


      t.timestamps
    end
  end
end

这是我的 User.rb 文件:

class User < ApplicationRecord
    has_secure_password
    has_many :events

    def User.digest(string)
        cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : BCrypt::Engine.cost
        BCrypt::Password.create(string, cost: cost)
    end
end

这是我的 Event.rb 文件:

class Event < ApplicationRecord
    belongs_to :user
end

【问题讨论】:

    标签: ruby-on-rails database rails-console


    【解决方案1】:

    您的表中没有外键。假设您实际上打算使用解释的模型(“事件属于用户”/“用户有很多事件”),您需要将列 user_id 添加到事件表,而不是 event 字符串到用户表。

    您可以使用 references 类型使用迁移/模型生成器创建迁移或列定义:

    rails g model event name:string user:references
    

    rails g migration add_user_id_to_event user:references
    

    这将添加列和所需的索引。

    此外,你有一个用户有很多个事件,所以没有什么像

    user.event = Event.create
    

    (没有User#event=这样的方法)而是

    user.events << Event.create(...)
    

    【讨论】:

      【解决方案2】:

      这不是一个简单的错误。这是相当多的事情是错误的。

      如果您想要一个用户可以拥有多个事件的关系,并且一个事件可以属于多个用户,您需要创建一个连接表。因为在用户表或事件表上存储外键会创建一对多的关系,这可能不是您想要的。

      class User < ApplicationRecord
        has_many :user_events
        has_many :events, through: :user_events
      end
      
      class Event < ApplicationRecord
        has_many :user_events
        has_many :users, through: :user_events
      end
      
      # this is a join model.
      class UserEvent < ApplicationRecord
        belongs_to :user
        belongs_to :event
      end
      

      has_many :through association 通常用于设置多对多 与另一个模型的连接。这种关联表明 声明模型可以与另一个的零个或多个实例匹配 通过第三种模型进行建模。 http://guides.rubyonrails.org/association_basics.html#the-has-many-through-association

      您可以通过运行生成UserEvent 模型和创建连接表的迁移:

      rails g model user_event user:belongs_to event:belongs_to
      

      这将创建一个带有user_idevent_id 外键列的user_events 表。您还应该回滚创建用户表的迁移并修复它:

      class CreateUsers < ActiveRecord::Migration[5.0]
        def change
          create_table :users do |t|
            t.string :name
            t.string :email
            t.string :password_digest # !!!
            t.integer :code
            t.timestamps
          end
        end
      end
      

      注意添加了password_digest 列 - 这是has_secure_password 所必需的。如果您已经在生产数据库上运行此迁移或提交并推送它,您应该创建单独的迁移来修复错误:

      class AddPasswordDigestToUsers < ActiveRecord::Migration[5.0]
        def change
          add_column(:users, :password_digest, :string)
        end
      end
      
      class RemoveEventFromUsers < ActiveRecord::Migration[5.0]
        def change
          remove_column(:users, :event)
        end
      end
      

      要创建与用户关联的事件,您可以执行以下操作:

      event = user.events.new(name: "Dummy") # does not persist the record
      event = user.events.create(name: "Dummy") 
      

      您可以使用铲子运算符从任一端分配记录:

      user.events << event
      event.users << user
      

      这对我来说合适吗?

      我的应用程序的主要目标是让用户有聚会和 那些派对有歌曲。

      只有一个用户的聚会听起来很蹩脚。但是,如果您想为用户创建特殊关系,您可以创建单独的关联:

      class User < ApplicationRecord
        has_many :user_events
        has_many :events, through: :user_events
        has_many :owned_events, class_name: 'Event', foreign_key: 'owner_id' 
      end
      
      class Event < ApplicationRecord
        has_many :user_events
        has_many :users, through: :user_events
        belongs_to :owner, class_name: 'User'
      end
      
      class AddOwnerIdToEvents < ActiveRecord::Migration[5.0]
        def change
          add_column(:events, :owner_id, :integer)
          add_foreign_key(:events, :users, column: :owner_id)
        end
      end
      

      解决此问题的另一种方法是在UserEvent 连接模型中添加一个列,该列指定关联是什么。但这远远超出了您的技能水平。

      【讨论】:

      • 感谢您对我的问题的深入描述。我最终让这些协会开始工作。我的最后一个问题是这是否会为每个用户分配一个事件。我的应用程序的主要目标是让用户拥有派对并且这些派对拥有歌曲。对于这个应用程序,我是否朝着正确的方向前进?
      • 你应该仔细阅读 Rails 指南 article on associationsactive record query interface
      • 好的,会的! :)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-05
      • 2015-07-03
      • 1970-01-01
      • 1970-01-01
      • 2013-02-03
      相关资源
      最近更新 更多