Rails 4:带有关联的 form_for [英] Rails 4: form_for with associations

查看:50
本文介绍了Rails 4:带有关联的 form_for的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Rails 和 ruby​​ 的新手.挣扎于 form_for 和关联.我正在尝试设置一个 Rails 应用程序,允许用户从客户端列表中进行选择.客户端通过 has_many :through 关系关联.我的模型按预期工作,我可以通过 rails 控制台向用户添加客户端.我现在想将此功能移至 Web 界面.下面的代码是我尝试的方式,但对我来说没有意义.我不确定哪个控制器操作是正确的操作.我应该在客户端的创建操作中处理表单 POST 吗?我实际上并不想创建一个新客户端,我只是希望用户从现有客户端列表中进行选择并创建关联.

我的模型如下:

class 客户端 :user_clientshas_many :user_clients, :dependent =>:破坏结尾类用户:user_clientshas_many :user_clients, :dependent =>:破坏结尾类 UserClient 

路线如下

资源:客户做资源:用户结尾资源:用户做资源:客户结尾

客户端控制器

class ClientsController <应用控制器before_action :set_client, only: [:show, :edit, :update, :destroy]定义索引如果参数[:user_id]@clients = User.find_by_id(params[:user_id]).clients别的@clients = Client.all结尾@客户结尾定义创建如果参数[:user_id]user = User.find(params[:user_id])客户端 = Client.find_by_id(params[:client_id])用户客户端<<客户用户保存重定向到 users_url别的@client = Client.new(client_params)@client.save重定向到clients_url结尾结尾结尾

客户端视图中的表单

new.html.erb

<% if params[:user_id] %><%= form_for([@user,@client]) 做 |f|%><div class="field"><%= f.label :id %><br><%= f.text_field :id %>

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

<%结束%><%其他%><%= 渲染表单"%><%结束%>

解决方案

首先,看看那个 gem:Nested表格.这里还有一些关于该主题的 railscasts.但是,如果您愿意构建自己的解决方案,则可以首先阅读有关嵌套属性的文档 此处.

希望有帮助!

更新.关于您的路线和一切.

资源:客户做资源:用户结尾资源:用户做资源:客户结尾

您在此处嵌套了资源.就像您在评论中提到的那样, users/:user_id/clients/newclients/new 将导致相同的操作.这就是这个路由的工作方式.您对Rails 做事风格 是正确的 - 在控制器中进行一些可怕的逻辑检查并基本上在一个动作中做不同的事情是非常糟糕的.由于您的操作(将用户与现有客户端相关联)与标准的 RESTful 操作集相去甚远(尽管最接近的变体是 update),您需要为您的资源引入新的操作 - 例如 <代码>assign_client.你可以这样做:

资源:用户做资源:客户会员做放置:assign_client结尾结尾

您可以在任何您喜欢的动作中渲染表单.但是,如果您想要更多独立的内容,您可以创建一对操作(例如 editupdate 对).第一个将呈现适当的表单,第二个将在服务器上处理该表单.

New to rails and ruby. Struggling with form_for and associations. I am trying to setup a rails app that allows a user to select from a list of clients. The clients are associated via has_many :through relationships. I have the models working as expected and I can add clients to users via the rails console. I now want to move this capability to the web interface. The below code is how I have tried, but it is just not making sense to me. I am unsure which controller action is the correct action. Should I process the form POST in the create action of the client? I am not actually wanting to create a new client, I just want the user to select from a list of existing clients and create the association.

My Models are as follows:

class Client < ActiveRecord::Base
has_many :users, :through => :user_clients
has_many :user_clients, :dependent => :destroy
end

class User < ActiveRecord::Base
has_many :clients, :through => :user_clients
has_many :user_clients, :dependent => :destroy
end

class UserClient < ActiveRecord::Base
belongs_to :user
belongs_to :client
end

Routes as follows

resources :clients do
  resources :users
end

resources :users do
  resources :clients
end 

Clients Controllers

class ClientsController < ApplicationController
  before_action :set_client, only: [:show, :edit, :update, :destroy]

  def index
    if params[:user_id]
      @clients = User.find_by_id(params[:user_id]).clients
    else
      @clients = Client.all
    end
    @clients
  end

  def create
    if params[:user_id]
      user = User.find(params[:user_id])
      client = Client.find_by_id(params[:client_id])
      user.clients << client
      user.save
      redirect_to users_url
    else
      @client = Client.new(client_params)
      @client.save
      redirect_to clients_url
    end
  end
end

Form in the client view

<h1>new.html.erb</h1>
<% if params[:user_id] %>
  <%= form_for([@user,@client]) do |f| %>
  <div class="field">
    <%= f.label :id %><br>
    <%= f.text_field :id %>
  </div>
  <div class="actions">
    <%= f.submit %>
  </div>
  <% end %>
<% else %>
  <%= render 'form' %>
<% end %>

解决方案

First, take a look at that gem: Nested Form. Here's also a couple of railscasts on the topic. However, if you're willing to build your own solution, you can start by reading documentation on nested attributes here.

Hope it helps!

Update. About your routes and everything.

resources :clients do
  resources :users
end

resources :users do
  resources :clients
end 

You've nested resources here. Like you mentioned in your comment, users/:user_id/clients/new and clients/new will lead to the same action. That's the way this routing works. You're correct about Rails style of doing things - that's pretty bad to make some scary logic checks in controller and do, basically, different things inside of one action. Since your action (associating user with existing client) is quite far from a standard set of RESTful actions (the closest variant will be update though), you need to introduce new action for your resource - for example assign_client. You can do it like this:

resources :users do
  resources :clients
  member do
    put :assign_client
  end
end

You can render form in any action you like. However, if you want something more standalone you can create a pair of actions (something like edit and update pair). The first one will render an appropriate form and the second one will process that form on the server.

这篇关于Rails 4:带有关联的 form_for的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
其他开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆