Criar uma lista ou uma lista de objectos em Ruby nos carris

estou tentando tornar possível para os usuários de uma aplicação web que estou construindo para criar listas de objetos que eles criaram.

por exemplo, o utilizador tem uma lista de objectos como Mercearias que podem ser qualquer coisa, desde maçãs a laranjas a pop-tarts.

Então gostaria que fosse possível devolver todas as compras adicionadas à base de dados pelo Usuário e criar uma lista selecionando aquelas que deveriam estar em seu supermercado. lista.

de preferência, este seria um estilo de modo a que eles pudessem clicar em opções para aqueles que queriam e, em seguida, clicar em save para criar uma nova lista.

eu procurei em belongs_to, has_many relacionamentos e tentei criar um objeto de lista que tem muitas compras, mas eu não consigo descobrir a forma parte desta estratégia. Agradecia qualquer conselho. Obrigado!

Aqui está o código que eu tenho atualmente, Eu o omiti originalmente porque eu não acho que eu estou no direito caminho, mas aqui está de qualquer forma apenas em caso/fornecer mais contexto:

Modelo De Mercearia:

class Item < ApplicationRecord
    belongs_to :list, optional: true
end

List Model

class List < ApplicationRecord
    has_many :items
end

O controlador da lista

class ListsController < ApplicationController
  before_action :authenticate_user!
  layout 'backend'

  def index
    @lists = List.where(user_id: current_user.id)
  end

  def show
  end

  def new
    @list = List.new
  end

  def edit
  end

  def create
    @list = List.new(list_params)
    @list.user = current_user

    if @list.save
      redirect_to list_path(@list.id), notice: 'List was successfully created.'
    else
      redirect_to list_path(@list.id), notice: 'List was not created.'
    end
  end

  def update
    respond_to do |format|
      if @list.update(list_params)
        format.html { redirect_to @list, notice: 'List was successfully updated.' }
        format.json { render :show, status: :ok, location: @list }
      else
        format.html { render :edit }
        format.json { render json: @list.errors, status: :unprocessable_entity }
      end
    end
  end

  def destroy
    @list.destroy
    respond_to do |format|
      format.html { redirect_to lists_url, notice: 'List was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Never trust parameters from the scary internet, only allow the white list through.
    def list_params
      params.require(:list).permit(:name, :items)
    end
end

não sei o que fazer sobre a forma-estava a tentar algo como http://apidock.com/rails/ActionView/Helpers/FormHelper/check_box

Author: Kevin, 2017-01-10

2 answers

Eu resolveria isto implementando um terceiro modelo que mantém a associação entre as compras e a lista. E então você pode lidar com isso de forma usando :accepts_nested_attributes_for.

Para dar um exemplo, aqui está como eu iria estruturar os modelos:

class List < ApplicationRecord
  has_many :list_items,   inverse_of: :list
  has_many :items,        through: :list_items

  # This allows ListItems to be created at the same time as the List, 
  # but will only create it if the :item_id attribute is present
  accepts_nested_attributes_for :list_items, reject_if: proc { |attr| attr[:item_id].blank? }
end

class Item < ApplicationRecord
  has_many :list_items
  has_many :lists,        through: :list_items
end

class ListItem < ApplicationRecord
  belongs_to :list, inverse_of: :list_items
  belongs_to :item
end

Com essa estrutura de modelo no lugar, aqui está um exemplo da vista para criar uma nova lista.

<h1>New List</h1>
<%= form_for @list do |f| %>
  <% @items.each_with_index do |item, i| %>
    <%= f.fields_for :list_items, ListItem.new, child_index: i do |list_item_form| %>
      <p>
        <%= list_item_form.check_box :item_id, {}, item.id, "" %> <%= item.name %>
      </p>
    <% end %>
  <% end %>
  <p>
    <%= f.submit 'Create List' %>
  </p>
<% end %>

Para explicar o que está a acontecer aqui, @items é uma variável pré-carregada para ter todos os itens que podem ser adicionados a um lista. Faço um loop através de cada Item e passo-o manualmente para o método do FormBuilder fields_for.

Porque faço isto manualmente, tenho de especificar o :child_index ao mesmo tempo, caso contrário cada opção obteria o mesmo atributo de nome (ou seja name="list[list_item_attributes][0][item_id]") que o item anterior e eles sobrepor-se-iam ao serem submetidos ao servidor.

E o método do Construtor de formulários check_box tem a seguinte declaração:

def check_box(method, options = {}, checked_value = "1", unchecked_value = "0")

Assim, na forma acima, eu substituo esses valores predefinidos de modo que, quando uma opção está assinalada, tem o valor de item.id e, se não estiver assinalada, o valor está em branco. Combine isto com a declaração de accepts_nested_attributes_for no modelo da lista, onde dizemos que deve ser rejeitado se o :item_id estiver em branco, e obtemos o resultado de apenas criar ListItems para os itens verificados.

A última coisa a fazer isto funcionar, é permitir os atributos aninhados no controlador, assim:

def allowed_params
  params.require(:list).permit(list_items_attributes: [:item_id])
end
 2
Author: DanneManne, 2017-01-10 07:28:09
Então eu encontrei a seguinte pergunta e usei-a para poder realizar o que eu queria.

Mostrar uma lista de opções em vez de várias opções

Eu simplesmente implementei o seguinte

<% form_for @list do |f| %>
  <% Item.all.each do |item|
    <%= f.check_box(:items, { :multiple => true }, item.id) %>
  <% end %>
<% end %>

Em que ponto eu tive o erro de que não havia nenhum list_id atribuído. Eu fiz uma migração a fim de adicionar attirbute "list_id" ao modelo de Item, e isso corrigiu-o e tudo funciona como eu queria.

Algum problema?
 0
Author: Kevin, 2017-05-23 11:54:39