自从我开始深入挖掘形式、关联、散列、符号以来已经快一周了……但如果没有你的帮助我似乎无法解决这个难题。
我正在开发一个用于显示不同画廊内容的项目。基本思想是当用户看到画廊的名称(名称是链接)时能够单击所选的画廊。然后显示属于该图库的所有图像。底部应该有一个链接“在此图库中添加图像”。
我的模型:
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 '在此处添加图片...',new_picture_path(:gallery_id=>@gallery.id) %>
在本例中,foreign_key:gallery_id 似乎暴露在浏览器的 URL 栏中。第二个问题是 :gallery_id 可用于控制器的“new”功能,但“消失”用于“create”功能(导致错误“无法找到没有 ID 的 Gallery”)。
当我在图片的 _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])
@[email protected]
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::HashWithIn DifferentAccess
画廊 ID:“6”
动作:新
控制器:图片
并在提交“创建”按钮后(引发异常):
{"utf8"=>"✓",
"authenticity_token"=>"IGI4MfDgbavBShO7R2PXIiK8fGjkgHDPbI117tcfxmc=",
"picture"=>{"image"=>"wilsonblx.png"},
"commit"=>"Create"}
如您所见,“图片”哈希中没有类似“gallery_id”的内容。
总结我的问题给你:
-
有没有办法在没有hidden_field的情况下传递foreign_key?
-
我可以以某种方式隐藏传递在 URL 栏中显示的外键表单吗?
-
是否有使用“link_to”传递参数的替代方法?
谢谢 。
It's been almost a week since I've began to dig deeper in forms , associations , hashes , symbols... But it seems I cannot solve the puzzle without your help .
I am working on a project for displaying different galleries content . The basic idea is when the user sees the names of galleries (names are links ) to be able to click on chosen one. Then all the images ,that belong to this gallery , are displayed . On the bottom there should be a link "Add image in this gallery" .
My models :
class Gallery < ActiveRecord::Base
attr_accessible :name
has_many :pictures
end
class Picture < ActiveRecord::Base
attr_accessible :image
belongs_to :gallery
end
I have created index on gallery_id for the 'pictures' table .
My big problem appears here , how to pass the gallery_id to the controller's action 'new' . As I've seen in "Agile web development with Rails" it could be :
<%= link_to 'Add a picture here...',new_picture_path(:gallery_id=>@gallery.id) %>
As it seems in this case the foreign_key :gallery_id is exposed in the URL bar of the browser . The second problem is that :gallery_id is available for the controller 'new' function , but "disappears" for the 'create' function (causing an error " Couldn't find Gallery without an ID ") .
The problem is gone when I add a hidden field in the _form for pictures , in my case :
<%= 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 %>
Here are my definitions in the 'pictures' controller :
def new
@gallery=Gallery.find(params[:gallery_id])
@[email protected]
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
And finaly the link_to definition in show.html.erb for galleries:
<% 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) %>
Here is the debug output before submitting the image :
--- !map:ActiveSupport::HashWithIndifferentAccess
gallery_id: "6"
action: new
controller: pictures
and after submitting the 'create' button (with exception raised ) :
{"utf8"=>"✓",
"authenticity_token"=>"IGI4MfDgbavBShO7R2PXIiK8fGjkgHDPbI117tcfxmc=",
"picture"=>{"image"=>"wilsonblx.png"},
"commit"=>"Create"}
As you see , there is nothing like "gallery_id" in the "pictures" hash .
Summarizing my questions to you :
-
Is there a way to pass the foreign_key without hidden_field ?
-
Could I hide somehow passing the foreign key form showing in the URL bar ?
-
Is there an alternative on passing arguments using 'link_to' ?
Thank you .
发布评论
评论(2)
您可能需要考虑阅读有关嵌套资源的 Rails 指南:
http://guides.rubyonrails。 org/routing.html#nested-resources
简而言之:
routes.rb
pictures_controller.rb
pictures/new.html.erb
好的,所以 gallery_id 仍然通过 URL 传递,但我没有真正看到任何东西错了。你必须把它传递到某个地方,对吧?对于将其传递到何处,您实际上只有 3 个明智的选择:隐藏字段、作为查询字符串参数,或隐藏在 URL(嵌套资源)内。在这 3 种方法中,后者是恕我直言最干净的方法。
如果您想让自己的事情变得更加轻松,我强烈建议您查看 Jose Valim 的 Inherited Resources gem,它可以为您解决很多此类样板问题:
https://github.com/josevalim/inherited_resources
You may want to consider reading the Rails Guide on nested resources:
http://guides.rubyonrails.org/routing.html#nested-resources
In a nutshell:
routes.rb
pictures_controller.rb
pictures/new.html.erb
Ok, so the gallery_id is still passed through the URL, but I don't really see anything wrong with that. You have to pass it somewhere, right? You really only have 3 sane choices on where to pass it: a hidden field, as a querystring parameter, or tucked away inside the URL (nested resource). Of the 3, the latter is IMHO the cleanest method.
If you want to make things even easier on yourself, I highly recommend looking into Jose Valim's Inherited Resources gem that takes care of a lot of this boilerplate nastiness for you:
https://github.com/josevalim/inherited_resources
您无需在 RESTful 路由中使用数字 ID。查看 permalink_fu,并使用 :permalink 字段而不是 :id 来引用每个图库资源。
这里的密钥
是使用一个符号化的、唯一的密钥,而不是 ID,永久链接对此非常有用。
您可以选择将永久链接作为 :id 传递,并更新您的控制器操作以实现这一点。
You need not use the numeric ID's in your RESTful routes. Look at permalink_fu, and use the :permalink field rather than the :id to refer to each gallery resource.
And
The key here is using a symbolic, unique key that's not the ID, permalink's are pretty good for that.
You can choose to pass the permalink in as :id and update your controller actions to expect that.