4

自从我开始深入研究表单、关联、哈希、符号以来已经快一周了……但如果没有你的帮助,我似乎无法解决这个难题。

我正在开发一个显示不同画廊内容的项目。基本思想是当用户看到画廊的名称(名称是链接)时,能够点击选择的画廊。然后显示属于该图库的所有图像。在底部应该有一个链接“在此图库中添加图片”。

我的模型:

 class Gallery < ActiveRecord::Base
attr_accessible  :name
has_many :pictures 
 end


class Picture < ActiveRecord::Base 
attr_accessible  :image 
belongs_to :gallery
 end

我在gallery_id 上为“图片”表创建了索引。

我的大问题出现在这里,如何将 gallery_id 传递给控制器​​的操作 'new' 。正如我在“使用 Rails 进行敏捷 Web 开发”中看到的那样:
<%= link_to 'Add a picture here...',new_picture_path(:gallery_id=>@gallery.id) %>

在这种情况下,foreign_key :gallery_id 似乎暴露在浏览器的 URL 栏中。第二个问题是 :gallery_id 可用于控制器的“新”功能,但“消失”用于“创建”功能(导致错误“找不到没有 ID 的画廊”)。当我在图片的_form中添加一个隐藏字段时,问题就消失了,就我而言:

<%= form_for(@picture)   do |f| %>
<div class="field"> 
      <%= f.hidden_field :gallery_id , :value=>params[:gallery_id] %>
<%= f.label :image %><br />
<%= f.file_field :image %>
</div>

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

这是我在“图片”控制器中的定义:

def new
@gallery=Gallery.find(params[:gallery_id])
@picture=@gallery.pictures.build 
 end


def create
   @gallery = Gallery.find(params[:gallery_id])  
   @picture = @gallery.pictures.new(params[:picture])
  if @picture.save
     redirect_to(@picture, :notice => 'Picture was successfully created.')
  else    
     redirect_to(galleries ,:notice => 'Picture was NOT created.')
  end

 end

最后是 show.html.erb 中画廊的 link_to 定义:

<% for picture in selpics(@gallery) %>
 <div id= "thumb" > 
 <%= image_tag picture.image %>
 </div>
<% end %>

 <%= link_to 'Add a picture here...',new_picture_path(:gallery_id=>@gallery.id) %>

这是提交图像之前的调试输出: --- !map:ActiveSupport::HashWithIndifferentAccess gallery_id: "6" action: new controller: pictures

并在提交“创建”按钮后(引发异常):

{"utf8"=>"✓",
 "authenticity_token"=>"IGI4MfDgbavBShO7R2PXIiK8fGjkgHDPbI117tcfxmc=",
 "picture"=>{"image"=>"wilsonblx.png"},
 "commit"=>"Create"}

如您所见,“图片”哈希中没有像“gallery_id”这样的东西。

总结我的问题给你:

  1. 有没有办法在没有 hidden_​​field 的情况下传递 foreign_key ?

  2. 我可以以某种方式隐藏通过 URL 栏中显示的外键表单吗?

  3. 是否有使用 'link_to' 传递参数的替代方法?

谢谢你 。

4

2 回答 2

7

您可能需要考虑阅读有关嵌套资源的 Rails 指南:

http://guides.rubyonrails.org/routing.html#nested-resources

简而言之:

路线.rb

resources :galleries do
  resources :pictures do
end
# Generates the routes: /galleries/:gallery_id/pictures

图片控制器.rb

def new
  @gallery = Gallery.find(params[:gallery_id])
  @picture = Picture.new
end
def create
  @gallery = Gallery.find(params[:gallery_id]) # gallery_id is passed in the URL
  @picture = @gallery.build(params[:picture])
  if @picture.save
  # success
  else
  # fail
  end
end

图片/new.html.erb

<%= form_for [@gallery, @picture] do |f| %>
  <div class="field"> 
    <%= f.hidden_field :gallery_id , :value=>params[:gallery_id] %>
    <%= f.label :image %><br />
    <%= f.file_field :image %>
  </div>

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

<% end %>

好的,gallery_id 仍然通过 URL 传递,但我真的看不出有什么问题。你必须把它传递到某个地方,对吧?您实际上只有 3 个明智的选择来传递它:隐藏字段,作为查询字符串参数,或隐藏在 URL 中(嵌套资源)。在这 3 个中,后者是恕我直言的最干净的方法。

如果您想让自己的事情变得更轻松,我强烈建议您查看 Jose Valim 的 Inherited Resources gem,它为您处理了很多这种样板文件:

https://github.com/josevalim/inherited_resources

于 2011-03-06T00:29:56.113 回答
0

您无需在 RESTful 路由中使用数字 ID。查看 permalink_fu,并使用 :permalink 字段而不是 :id 来引用每个画廊资源。

/galleries/louvre
/galleries/moma/382

... new_picture_path(:gallery_id => @gallery.permalink)

这里的关键是使用不是 ID 的符号唯一键,永久链接非常适合。

您可以选择将永久链接作为 :id 传递并更新您的控制器操作以实现预期。

于 2011-03-06T00:23:50.440 回答