Rails 4:带有关联的 form_for [英] Rails 4: form_for with associations
问题描述
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/new
和 clients/new
将导致相同的操作.这就是这个路由的工作方式.您对Rails 做事风格 是正确的 - 在控制器中进行一些可怕的逻辑检查并基本上在一个动作中做不同的事情是非常糟糕的.由于您的操作(将用户与现有客户端相关联)与标准的 RESTful 操作集相去甚远(尽管最接近的变体是 update
),您需要为您的资源引入新的操作 - 例如 <代码>assign_client.你可以这样做:
资源:用户做资源:客户会员做放置:assign_client结尾结尾
您可以在任何您喜欢的动作中渲染表单.但是,如果您想要更多独立的内容,您可以创建一对操作(例如 edit
和 update
对).第一个将呈现适当的表单,第二个将在服务器上处理该表单.
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屋!