我创建了一个如下所示的表单类:
class UserForm
include ActiveModel::Model
attr_accessor :name, :phone_number,:address1, :address2
validates :name, presence: true
def create_user
User.create! do |u|
u.name = name
u.phone_number = phone_number
u.address1 = address1
u.address2 = address2
end
end
def update_user(user)
user.name = name
user.phone_number = phone_number
user.address1 = address1
user.address2 = address2
user.save
end
end
当我使用类似UserForm.new({name: 'x', phone_number: 'z'})
的哈希值初始化时,我创建了与实例变量一样多的attr_accessor。
如何避免重复创建和更新中的代码?我为用户提供了更多属性,并且我试图避免在创建和更新中重复所有这些属性。
答案 0 :(得分:2)
改为使用Rails方式。
我会说你正在做的事情很可能是不必要的。在Rails中,控制器将输入传递给模型 - 模型处理验证该输入。 Form builders将绑定模型属性和错误处理为html。
所以"表格类"根本没有像Symfony 2这样的其他框架中的内容。实际上,您可能只是添加了另一级别的重复和间接,而不是干掉您的应用程序。
在rails中创建模型实例时,无需绑定属性1-1。 Rails模型初始化器和工厂方法采用属性哈希:
User.new(name: "Max", awesome: true)
User.create(name: "Max", awesome: true) # this is just .new and .save
Rails的方法是设置表单输入,以便它们与模型属性对齐:
<%= form_for(@user) do |f| %>
<div class="row">
<%= f.label :name %>
<%= f.text_input :name %>
</div>
<div class="row">
<%= f.label :awesome %>
<%= f.check_box :awesome %>
</div>
<% end %>
然后在您的控制器中,您只需白名单并将参数传递给模型初始值设定项:
class UserController < ApplicationController
before_action :set_user, only: [:show, :edit, :update, :destroy]
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
redirect_to @user
else
render :new
end
end
def update
if @user.update(user_params)
redirect_to @user
else
render :edit
end
end
private
def set_user
@user = User.find(params[:id])
end
def user_params
params.require(:user).permit(:name, :awesome)
end
end
如果您想干掉控制器,可以使用responders和过滤器。如果您需要共享方法,您将使用关注点或经典继承。
def create
@user = User.create(user_params)
respond_with(@user)
end
要重复使用表单和表单组件,请使用partials:
# app/views/users/new.html.erb
<h1>Create a new user</h1>
<% render partial: 'form' %>
# app/views/users/edit.html.erb
<h1>Editing <%= @user.name %></h1>
<% render partial: 'form' %>
答案 1 :(得分:0)
您可以创建一个方法,将实例变量公开为哈希...
class UserForm
include ActiveModel::Model
attr_accessor :name, :phone_number,:address1, :address2
validates :name, presence: true
def attrs
(instance_variables.map{|i| [i.to_s[1..-1].to_sym, instance_variable_get(i)]}).to_h
end
def create_user
User.create!(attrs)
end
def update_user(user)
user.update_attributes(attrs)
end
end