Rails - 如何一次记录两个引用ID

时间:2015-07-03 02:35:17

标签: ruby-on-rails ruby devise

我的一个表格中只设置了两个参考ID中的一个。

模式

enter image description here

模型

tech.rb

class Tech < ActiveRecord::Base
    has_many :services
end

service_menu

class ServiceMenu < ActiveRecord::Base
  has_many :services
end

service.rb

class Service < ActiveRecord::Base
  belongs_to :tech
  belongs_to :service_menu
end

控制器

services_controller.rb

def new
    @service = current_tech.services.build
end

def create
    @service = current_tech.services.build(service_params)

    respond_to do |format|
      if @service.save
        format.html { redirect_to @service, notice: 'Service was successfully created.' }
        format.json { render :show, status: :created, location: @service }
      else
        format.html { render :new }
        format.json { render json: @service.errors, status: :unprocessable_entity }
      end
    end
end

private

def service_params
  params.require(:service).permit(:name)
end

查看

<%= simple_form_for @service do |f| %>
  <div class="field">
    <%= f.label "Select service category" %>
    <br>

    <%= collection_select(:service, :name, ServiceMenu.all, :name, :name, {:prompt => true }) %>
  </div>

  <div class="actions">
    <%= f.submit %>
  </div>
<% end %>

每当我创建一个新服务时,只记录tech_id而不记录service_menu_id。 如何创建一个能够同时将tech和service_menu id记录到服务表的新服务?

感谢任何帮助。

  

编辑7/3美国东部时间下午2:55

@Yen-Ju方法起初并不适合我,但现在确实如此。起初,我未能正确引用service_menu_id中的services table

我的services db之前:

| Field           | Type         | Null | Key | Default | Extra          |
+-----------------+--------------+------+-----+---------+----------------+
| id              | int(11)      | NO   | PRI | NULL    | auto_increment |
| name            | varchar(255) | YES  |     | NULL    |                |
| tech_id         | int(11)      | YES  | MUL | NULL    |                |
| service_menu_id | int(11)      | YES  |     | NULL    |                |
| created_at      | datetime     | NO   |     | NULL    |                |
| updated_at      | datetime     | NO   |     | NULL    |                |
+-----------------+--------------+------+-----+---------+----------------+

以前不工作的原因是MUL列下没有KEY值。

我的services db现在:

| Field           | Type         | Null | Key | Default | Extra          |
+-----------------+--------------+------+-----+---------+----------------+
| id              | int(11)      | NO   | PRI | NULL    | auto_increment |
| name            | varchar(255) | YES  |     | NULL    |                |
| tech_id         | int(11)      | YES  | MUL | NULL    |                |
| service_menu_id | int(11)      | YES  | MUL | NULL    |                |
| created_at      | datetime     | NO   |     | NULL    |                |
| updated_at      | datetime     | NO   |     | NULL    |                |
+-----------------+--------------+------+-----+---------+----------------+

这也允许我删除name数据库中的services列,因为它不再需要。

感谢所有回复的人。

4 个答案:

答案 0 :(得分:1)

您需要为模型添加has_many :through关系:

<强> tech.rb

class Tech < ActiveRecord::Base
  has_many :services
  has_many :service_menus, through: :services
end

<强> service_menu.rb

class ServiceMenu < ActiveRecord::Base
  has_many :services
  has_many :techs, through: :services
end

<强> service.rb

class Service < ActiveRecord::Base
  belongs_to :tech
  belongs_to :service_menu
end

执行此操作后,Active Record会为您处理连接模型(服务)内务处理。您可以在Rails控制台中演示:

>> tech = Tech.create(name: "bar")
   (0.2ms)  begin transaction
  SQL (0.4ms)  INSERT INTO "techs" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "bar"], ["created_at", "2015-07-03 23:30:26.893615"], ["updated_at", "2015-07-03 23:30:26.893615"]]
   (10.7ms)  commit transaction
=> #<Tech id: 4, name: "bar", created_at: "2015-07-03 23:30:26", updated_at: "2015-07-03 23:30:26">
>> tech.service_menus << ServiceMenu.create(name: "baz")
   (0.1ms)  begin transaction
  SQL (0.4ms)  INSERT INTO "service_menus" ("name", "created_at", "updated_at") VALUES (?, ?, ?)  [["name", "baz"], ["created_at", "2015-07-03 23:31:21.045841"], ["updated_at", "2015-07-03 23:31:21.045841"]]
   (18.9ms)  commit transaction
   (0.1ms)  begin transaction
  SQL (0.5ms)  INSERT INTO "services" ("tech_id", "service_menu_id", "created_at", "updated_at") VALUES (?, ?, ?, ?)  [["tech_id", 4], ["service_menu_id", 4], ["created_at", "2015-07-03 23:31:21.072932"], ["updated_at", "2015-07-03 23:31:21.072932"]]
   (33.1ms)  commit transaction
  ServiceMenu Load (0.3ms)  SELECT "service_menus".* FROM "service_menus" INNER JOIN "services" ON "service_menus"."id" = "services"."service_menu_id" WHERE "services"."tech_id" = ?  [["tech_id", 4]]
=> #<ActiveRecord::Associations::CollectionProxy [#<ServiceMenu id: 4, name: "baz", created_at: "2015-07-03 23:31:21", updated_at: "2015-07-03 23:31:21">]>
>> Service.first
  Service Load (0.4ms)  SELECT  "services".* FROM "services"  ORDER BY "services"."id" ASC LIMIT 1
=> #<Service id: 2, tech_id: 4, service_menu_id: 4, created_at: "2015-07-03 23:31:21", updated_at: "2015-07-03 23:31:21">`

答案 1 :(得分:1)

我没有测试代码,但这可能有用。

首先,更改视图以设置 service_menu_id

    <%= collection_select(:service, :service_menu_id, ServiceMenu.all, :id, :name, {:prompt => true }) %>

其次,在您的控制器中,允许 service_menu_id 传递:

def service_params
  params.require(:service).permit(:service_menu_id)
end

然后,当您构建服务时, service_menu_id 将成功传递。

答案 2 :(得分:0)

您需要进行以下更改。

20dp

中添加service_menu_id
servuce_params

并改变您的观看代码

def service_params
  params.require(:service).permit(:name, :service_menu_id)
end

答案 3 :(得分:0)

如果您使用postrgesql,则可以在call.bind(frombulate)中阅读此ActiveRecord documentation并使用bind作为您的任务。

例如:

1.6 Composite Types