Rails: установить значение, используя ссылку - PullRequest
3 голосов
/ 13 июля 2011

Мне нужна помощь при попытке создать ссылку, которая отправляет форму редактирования.

Допустим, у меня есть список объектов

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

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 %>

Ответы [ 2 ]

3 голосов
/ 13 июля 2011

Это все о том, как вы настраиваете действия своего контроллера.Я не совсем уверен, что понимаю, как вы хотите использовать свой, но у меня есть аналогичный случай, который я покажу вам, который, я думаю, вы должны быть в состоянии приспособиться к вашей ситуации.

В моем случае,У меня есть кнопка меню, которая устанавливает значение в сеансе, чтобы держать панель меню открытой или закрытой для любых представлений, на которые смотрит пользователь.

Во-первых, вам нужно действие контроллера, которое выполнит работу, которую вы выполняете.Вы заинтересованы. Я создал «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 или advanced_search истинным, и если это так, они показывают представление.

Вы можете использовать ту же логику.Примерно так:

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

Чтобы запустить это действие контроллера со ссылкой, вам необходим маршрут, который принимает запросы GET.edit - логичный выбор.

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

Примечание: я думаю, что SharedController имеет больше смысла, чем SharedsController, а edit_shared_path имеет больше смысла, чем edit_shareds_path,поэтому я должен был указать :controller => 'shared' в моем маршруте.


Тогда вам просто нужна ссылка на 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-запросы, что означает, что вы переходите к действию EDIT.См .: 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

Надеюсь, что все имеет смысл.

1 голос
/ 13 июля 2011

Метод edit_toy_path, который вызывает ваш метод link_to, переходит к действию edit внутри вашего контроллера. Это не тот метод update, который, я полагаю, вы хотите.

Ваш link_to должен будет измениться на что-то вроде:

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

Но я подвергаю сомнению этот конкретный подход. Я не думаю, что переменная будет корректно обновляться в действии update, поскольку она не имеет пространства имен для правильного params[:toy] объекта, который ожидает update_attributes. И в моих быстрых и грязных тестах я не мог правильно передать его в пространство имен.

Когда у меня есть ситуация, подобная той, которую вы описываете, я обычно настраиваю другое действие, например toggle_ownership, и я называю это из моего link_to с опцией :remote => 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, который обновляет соответствующий раздел страницы.

Надеюсь, это поможет!

...