Rails 4 - 如何将Model的2列映射到另一个模型的另一列

时间:2015-09-18 10:38:25

标签: ruby-on-rails ruby ruby-on-rails-4

我想将同一模型的两列(dev_statustest_planning_status)映射到另一个模型的列(Status.name),并希望将UserStory形式映射到来自Status

的值的下拉列表

我尝试了类似的东西,但无法弄清楚

状态模型是这样的

class Status < ActiveRecord::Base
  has_many :dev_status, :class_name => 'UserStory', :foreign_key => 'dev_status_id'
  has_many :test_planning_status, :class_name => 'UserStory', :foreign_key => 'test_planning_status_id'
end

目前我在models / UserStory

中有这个
class UserStory < ActiveRecord::Base
validates :us_number, presence: true
validates :team_id, presence: true
validates :dev_status,  presence:true
validates :test_status,  presence:true
belongs_to :team

CreateUserStories迁移

class CreateUserStories < ActiveRecord::Migration
   def change
     create_table :user_stories do |t|
     t.string :us_number
     t.references :team
     t.string :dev_status
     t.string :test_planning_status
     t.integer :tc_count
     t.timestamps null: false
  end
  add_foreign_key :user_stories, :pod
end

我的UserStoryController参数是

def user_story_params
  params.require(:user_story).permit(:us_number, :team_id, :dev_status, :test_planning_status)
end

UserStory _form是

<%= f.label :dev_status,'Dev Status' %>
    <%= f.select :status, Status.all.map {|u|[u.status, u.id]}, 
                                      {include_blank: true} %>

<%= f.label :test_planning_status, 'Test Planning Status' %>
    <%= f.select :status, Status.all.map {|u|[u.status, u.id]}, 
                                      {include_blank: true} %>

2 个答案:

答案 0 :(得分:1)

目标应该是调用UserStory.dev_status.name来获取dev_status名称,并UserStory.test_planning_status.name来获取test_planning_status名称。

  1. 您的迁移应该是创建列dev_status_id(不是dev_status)和test_planning_status_id(不是test_planning_status)。

    在将来的迁移中使用t.referencest.belongs_to

  2. 上面的列应该是整数,而不是字符串。

  3. 您需要在belongs_to对象上为您的状态字段指定UserStory

    belongs_to :dev_status, class_name: 'Status'
    belongs_to :test_planning_status, class_name: 'Status'
    
  4. 更改

    validates :test_status, presence:true

    validates :test_planning_status, presence:true

  5. 表单中的两个f.select :status需要更改为f.select :test_planning_statusf.select :dev_status

  6. 这应该让你指出正确的方向。希望它有所帮助!

答案 1 :(得分:1)

这听起来像标准has_many relationship ::

class Status < ActiveRecord::Base
   # columns id | name | value | other | information | created_at | updated_at
   has_many :user_stories
end

class UserStory < ActiveRecord::Base
   # columns id | title | value | dev_status_id | test_planner_status | created_at | updated_at
   belongs_to :dev_status, class_name: :status
   belongs_to :test_planning_status, class_name: :status
end

这将使您能够访问以下内容:

#app/controllers/statuses_controller.rb
class UserStoriesController < ActionController::Base
   def show
      @story = UserStory.find params[:id]
      #@story.dev_status = gives you dev's details, with status value from Status table
   end
end

如果您想避开law of demeter(IE只有一个点可以访问您的数据),您将需要使用delegate方法:

#app/models/user_story.rb
Class UserStory < ActiveRecord::Base
    delegate :name to: :dev_status, prefix: true
    # this will allow you to call @user.dev_status_name
end

如果您希望更改状态,则可以使用collection_select帮助程序来处理Status个对象:

#app/views/user_stories/edit.html.erb
...
<%= f.collection_select :dev_status_id, Status.all, :id, :name, prompt: true %>
<%= f.collection_select :test_planner_status, Status.all, :id, :name, prompt: true %>

-

<强> ActiveRecord的

enter image description here

您必须记住模型内置 ,它们只是类。 Rails使用ORMActiveRecord)来提取数据以填充这些类。

许多人对models如何适应Rails生态系统感到困惑。模型由“属性”组成,您必须手动或通过Rails ORM API填充这些属性。您的User模型IE可能具有以下内容:

#app/models/user.rb
class User < ActiveRecord::Base
    def will_you_marry_me?
       "no"
    end
end

#app/views/application.html.erb
Will the user marry? 
<%= @user.will_you_marry_me? %>

当您谈到“映射”列时,您真正要问的是如何将不同的表的数据调用到模型类中的属性。例如,如果您有User类,则如何使用@user.birthday表格等中的数据填充profiles

答案是使用ActiveRecord的关系结构。关系数据库只需与foreign_keys一起使用即可从其他表加载数据。例如,您可以使用profiles表格user_id来获取有关特定用户的信息(请参阅上图)。

ActiveRecord使加载“其他表”数据的过程非常简单。通过使用API​​中的关系,您可以使用has_many

等数据填充数据