0

我正在使用 Rails v4,并且我有一个通过脚手架生成的控制器。我希望更新操作的路由基于machine_name我定义的模型的属性,而不是 ID。但是,在 routes.rb 中,正在通过资源为模型生成路由。

所以这里是资源的默认路由:

                rooms GET    /rooms(.:format)                           rooms#index
                      POST   /rooms(.:format)                           rooms#create
             new_room GET    /rooms/new(.:format)                       rooms#new
            edit_room GET    /rooms/:id/edit(.:format)                  rooms#edit
                 room GET    /rooms/:id(.:format)                       rooms#show
                      PATCH  /rooms/:id(.:format)                       rooms#update
                      PUT    /rooms/:id(.:format)                       rooms#update
                      DELETE /rooms/:id(.:format)                       rooms#destroy

因此,对于 PATCH/PUT 请求,更新方法将在我提交时触发,例如 /rooms/folsom_prison。然后,Rails 会将 folsom_prison 视为 ID,并尝试将参数与id列中的值匹配,而不是与machine_name列匹配。如何让 Rails 更改它正在查找记录的列?

我正在使用的当前代码:

  # PATCH/PUT /rooms/1
  # PATCH/PUT /rooms/1.json
  def update
    @room = Room.find_by_machine_name(params[:id])
    room_params.delete(:id)
    respond_to do |format|
      if Room.update(@room.id,room_params)
        format.html { redirect_to @room, notice: 'Room was successfully updated.' }
        format.json { head :no_content }
      else
        format.html { render action: 'edit' }
        format.json { render json: @room.errors, status: :unprocessable_entity }
      end
    end
  end

日志中产生的错误消息:

Started PATCH "/rooms/folsom_prison" for 127.0.0.1 at 2013-09-13 16:28:53 -0400
  Room Load (0.1ms)  SELECT "rooms".* FROM "rooms" WHERE "rooms"."id" = ? LIMIT 1  [["id", "folsom_prison"]]

ActiveRecord::RecordNotFound (Couldn't find Room with id=folsom_prison):
  app/controllers/rooms_controller.rb:69:in `set_room'

...以及我要测试的 cURL 请求:

curl -i -H "Accept: application/json" -X PATCH -d "room[booked]=1" localhost:3000/rooms/folsom_prison
4

3 回答 3

1

您正在寻找friendly_id gem:https ://github.com/norman/friendly_id

于 2013-09-13T20:56:07.267 回答
1

您不想find_by_*在 Rails 4 中使用助手。这就是您想要做的

Room.where(machine_name: params[:id])

为了让您的路线正常工作,您需要to_paramRoom模型中覆盖

require "uri"

class Room < ActiveRecord::Base
  # ...

  def to_param
    URI.escape(machine_name)
  end
end

假设你有一个房间实例

@room = Room.new machine_name: "foo"

当您创建链接时,一切都会很棒!

<%= link_to @room.machine_name, @room %>
#=> <a href="/rooms/foo">foo</a>
于 2013-09-13T21:04:07.807 回答
0

@naomik 对贬低的find_by_*方法是正确的,但是,已经被find_by方法取代,而不是where.

Room.find_by(machine_name: params[:id])

这将找到 1 条记录并将其返回,但where将找到与此匹配的所有记录,并始终以数组的形式返回它们,即使只有一条记录。

于 2014-10-24T17:05:30.830 回答