Rails:使用链接设置值

发布于 2024-11-19 20:41:56 字数 879 浏览 2 评论 0原文

我需要帮助尝试创建提交编辑表单的链接。

假设我有一个对象列表

Object -   Color -   Own? 
Ball   -   Red   -  false   - [button]
Hat    -   Blue  -  true    - [button]
Shoe   -   Green -  false   - [button]

,当我单击[按钮]时,我想设置“自己的?”为真。

路线

  resources :toys

控制器

def edit
    @toy = Toy.find(params[:id])
end

def update
  @toy = Toy.find(params[:id])
  if @Toy.update_attributes(params[:toy])
    flash[:notice] = "Toy Updated"
    redirect_to @toy
  else
    render 'edit'
  end
end

视图

<h2>Toys</h2>
    <% if @toys %>
    <% @toys.each do |toy| %>
          <%= toy.name %> - <%= link_to 'Set Own', edit_toy_path(:id=>toy.id, :owned=>'true')%>
    <br/>
    <% end %>
<% else %>
    None
<% end %>

I need help trying to create a link that submits an edit form.

Let's say I have a list of objects

Object -   Color -   Own? 
Ball   -   Red   -  false   - [button]
Hat    -   Blue  -  true    - [button]
Shoe   -   Green -  false   - [button]

When I click on the [button] I want to set "Own?" to True.

Routes

  resources :toys

Controller

def edit
    @toy = Toy.find(params[:id])
end

def update
  @toy = Toy.find(params[:id])
  if @Toy.update_attributes(params[:toy])
    flash[:notice] = "Toy Updated"
    redirect_to @toy
  else
    render 'edit'
  end
end

View

<h2>Toys</h2>
    <% if @toys %>
    <% @toys.each do |toy| %>
          <%= toy.name %> - <%= link_to 'Set Own', edit_toy_path(:id=>toy.id, :owned=>'true')%>
    <br/>
    <% end %>
<% else %>
    None
<% end %>

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

煮酒 2024-11-26 20:41:57

link_to 方法调用的 edit_toy_path 方法将转到控制器内的 edit 操作。我猜你想要的不会是 update 方法。

您的 link_to 需要更改为以下内容:

<%= link_to 'Set Own', toy_path(:id=>toy.id, :owned=>'true'), :method => :put %>

但我对这种特殊方法提出质疑。我认为该变量不会在更新操作中正确更新,因为它没有命名为 update_attributes 期望的正确 params[:toy] 对象。在我的快速而肮脏的测试中,我无法将其正确地放入命名空间。

当我遇到像您所描述的情况时,我通常会设置另一个操作,例如 toggle_ownership ,并使用 :remote => 从我的 link_to 调用该操作; true 选项。然后控制器根据需要切换属性。

因此,我的路线看起来像这样:

resources :toys do
  member do
    put :toggle_ownership
  end
end

我的视图看起来像

<%= link_to 'Set Own', toggle_ownership_toy_path(toy.id), :method => :put %>

控制器设置变量并渲染回一个 toggle_ownership.js.erb 文件,该文件更新页面的相应部分。

希望有帮助!

The edit_toy_path method that your link_to method is calling is going to the edit action inside your controller. It's not going to the update method that I'm guessing you want.

Your link_to will need to change to something like:

<%= link_to 'Set Own', toy_path(:id=>toy.id, :owned=>'true'), :method => :put %>

But I question this particular approach. I don't think the variable will update correctly in the update action because it is not namespaced to the proper params[:toy] object that update_attributes is expecting. And in my quick and dirty tests I couldn't get it to namespace properly.

When I have a situation like the one that you are describing I usually setup another action, like toggle_ownership and I call that from my link_to with a :remote => true option. Then the controller toggles the attributes as desired.

Thus, my routes looks something like:

resources :toys do
  member do
    put :toggle_ownership
  end
end

And my view looks like

<%= link_to 'Set Own', toggle_ownership_toy_path(toy.id), :method => :put %>

The controller sets the variable and renders back a toggle_ownership.js.erb file that updates the appropriate section of the page.

Hope that helps!

莫言歌 2024-11-26 20:41:56

这完全取决于您如何设置控制器操作。我不完全确定我理解你想如何使用你的,但我有一个类似的案例,我将向你展示我认为你应该能够适应你的情况。

就我而言,我有一个菜单按钮,它在会话中设置一个值,以在用户查看的任何视图中保持菜单面板打开或关闭。

首先,您需要一个控制器操作来完成您感兴趣的工作。我创建了一个“SharedController”,它处理不属于任何特定视图或其他控制器的应用程序范围的事情。

class SharedController < ApplicationController

  # Used by AJAX links to set various settings in shared views
  def edit
    session[:admin_menu] = params[:admin_menu].to_sym if params[:admin_menu]
    session[:advanced_search] = params[:advanced_search].to_sym if params[:advanced_search]

    render :nothing => true
  end
end

此控制器操作可以在会话中设置两个值之一:“admin_menu”(布尔值)或“advanced_search”(布尔值)。然后某些视图会询问 admin_menu 或 advance_search 的会话值是否为 true,如果是,则显示该视图。

您可以使用相同的逻辑。类似于:

def edit
  object= Object.find(params[:object_id])
  object.own = params[:own]
  object.save
end

要使用链接触发此控制器操作,您需要有一个接受 GET 请求的路由。 edit 是一个合乎逻辑的选择。

resource :shared, :only => [:edit], :controller => 'shared'

注意:我认为 SharedControllerSharedsController 更有意义,而 edit_shared_pa​​thedit_shareds_path 更有意义,所以我必须指定 :controller =>; 'shared'在我的routes.rb中。


然后你只需要一个带有参数的url链接。要将参数添加到路径上,只需将它们添加到路径帮助器中,如下所示:

edit_shared_path(:key => 'value')

您可以通过以下方式在控制器中检索这些参数:

params[:key]

将其设置为链接,如下所示:

link_to 'Set Own to True for This Object', edit_shared_path(:object_id=>object.id, :own=>'true')

注意:最好通过 AJAX 执行此操作,因此可以请务必设置 :remote=>true。如果您不使用 AJAX,那么您需要在控制器中指定一个重定向,以便在触发此链接后应加载哪个页面。


对于我的管理菜单首选项链接,我需要一个包含两个可能的链接州。我使用助手生成这些:

  # Shows Admin Menu Button
  def admin_toggle_button
    if session[:admin_menu] == :on
      link_to( 'Admin Tools', edit_shared_path(:admin_menu => :off), :remote=>true, :class => 'selected', :id => 'admin_toggle_button', :title => 'Hide Admin Menu' )
    else
      link_to( 'Admin Tools', edit_shared_path(:admin_menu => :on), :remote=>true, :id => 'admin_toggle_button', :title => 'Show Admin Menu' )
    end
  end

在视图中,我只是使用 admin_toggle_button 调用它。如果您愿意,您可以做类似的事情,但这是可选的。

我希望这能让您走上正轨,如果您有任何疑问,请告诉我。


编辑:根据您的评论:

链接发出 GET 请求,这意味着您将进行编辑操作。请参阅:http://guides.rubyonrails.org/routing.html#crud -verbs-and-actions

进一步的问题是,您有 resources :toys 而不是 resource :shared (我用于此目的)。这意味着您的链接助手已经期望编辑特定的玩具,而不是处理单个资源。请参阅:http://guides.rubyonrails.org/routing.html#singular-resources

如果您将其更改为:

link_to 'Set Own', edit_toy_path(@toy, :owned=>'true'), :remote => true

...并将控制器中的编辑操作设置为以下内容,则链接将起作用:

def edit
  @toy = Toy.find(params[:id])
  @toy.owned = params[:owned]
  if @toy.save!
    head :ok
  else
    head :internal_server_error
  end
end

请参阅:http://guides.rubyonrails.org/layouts_and_rendering.html #using-head-to-build-header-only-responses

现在,请注意,您确实应该只使用 AJAX 链接执行此操作,并且通常不应该使用您的“真正的”控制器。原因是,现在这是唯一可以通过 EDIT 处理的操作,因此您的正常 toys#edit 视图将不再起作用。

您可以通过创建新操作和新路线来解决此问题,例如:

resources :toys do
  member do
    get 'set_ownership'
  end
end

然后只需采用上面相同的方法并将其命名为 set_ownership 而不是 edit。 IE:

class ToysController < ApplicationController
  ...
  def set_ownership
    ...
  end 
end

希望一切都有意义。

This is all about how you setup your controller actions. I'm not totally sure I understand how you want to use yours, but I have a similar case that I'll show you which I think you should be able to adapt to your situation.

In my case, I have a menu button that sets a value in the session to either keep a menu panel open or closed across any views a user looks at.

First, you need a controller action that is going to do the work you're interested in. I created a "SharedController" which handles application-wide things that don't belong to any particular view or other controller.

class SharedController < ApplicationController

  # Used by AJAX links to set various settings in shared views
  def edit
    session[:admin_menu] = params[:admin_menu].to_sym if params[:admin_menu]
    session[:advanced_search] = params[:advanced_search].to_sym if params[:advanced_search]

    render :nothing => true
  end
end

This controller action can set one of two values in the session, either: "admin_menu" (boolean) or "advanced_search" (boolean). Then certain views ask whether the session value for admin_menu or advanced_search is true, and if so they show the view.

You could use the same logic. Something like:

def edit
  object= Object.find(params[:object_id])
  object.own = params[:own]
  object.save
end

To trigger this controller action with a link you need to have a route that accepts GET requests. edit is a logical choice.

resource :shared, :only => [:edit], :controller => 'shared'

Note: I think SharedController makes more sense than SharedsController, and edit_shared_path makes more sense than edit_shareds_path, so I had to specify :controller => 'shared' in my routes.rb.


Then you just need a link to a url with params. To add params onto a path you just add them to the path helper, like so:

edit_shared_path(:key => 'value')

You can retrieve these params in your controller via:

params[:key]

Make this a link like so:

link_to 'Set Own to True for This Object', edit_shared_path(:object_id=>object.id, :own=>'true')

NOTE: It's best to do this via AJAX, so be sure to set :remote=>true. If you don't use AJAX then you need to specify a redirect in your controller for what page should be loaded after this link is triggered.


In the case of my admin menu preference link, I need a link with two possible states. I generate these using a helper:

  # Shows Admin Menu Button
  def admin_toggle_button
    if session[:admin_menu] == :on
      link_to( 'Admin Tools', edit_shared_path(:admin_menu => :off), :remote=>true, :class => 'selected', :id => 'admin_toggle_button', :title => 'Hide Admin Menu' )
    else
      link_to( 'Admin Tools', edit_shared_path(:admin_menu => :on), :remote=>true, :id => 'admin_toggle_button', :title => 'Show Admin Menu' )
    end
  end

In a view I just call this using admin_toggle_button. You can do something similar if you like, but it's optional.

I hope that gets you on the right track, let me know if you have any questions.


EDIT: Based on your comment:

Links issue GET requests, which mean you're going to the EDIT action. See: http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions

A further issue, you have resources :toys instead of resource :shared (which I used for this purpose). This means your link helper is already expecting a specific toy to edit, rather than handling a singular resource. See: http://guides.rubyonrails.org/routing.html#singular-resources

Your link would work if you changed it to be:

link_to 'Set Own', edit_toy_path(@toy, :owned=>'true'), :remote => true

... and set your edit action in your controller to the following:

def edit
  @toy = Toy.find(params[:id])
  @toy.owned = params[:owned]
  if @toy.save!
    head :ok
  else
    head :internal_server_error
  end
end

See: http://guides.rubyonrails.org/layouts_and_rendering.html#using-head-to-build-header-only-responses

Now, be aware, you really should only do this with AJAX links, and you should normally not do it with your "real" controller. The reason is, now this is the only action that can be processed by EDIT, so your normal toys#edit view would no longer work.

You can get around this by create a new action and a new route, for instance:

resources :toys do
  member do
    get 'set_ownership'
  end
end

Then simply take the same method above and call it set_ownership instead of edit. IE:

class ToysController < ApplicationController
  ...
  def set_ownership
    ...
  end 
end

Hope that all makes sense.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文