我对Rails很陌生,非常感谢任何帮助。我创建了以下方法:
def name_fix
name = self.split
mod_name = []
name.each do |n|
n.split("")
if n[0]
n.upcase
else
n.downcase
end
mod_name.push(n)
end
mod_name.join
end
我想在我的Controller中使用此方法:
def create
@patient = Patient.new(params[:patient])
@patient.name = params[:params][:name].name_fix
if @patient.save
redirect_to patients_path
else
render :new
end
end
我该如何完成这项工作?此方法是否位于我的模型或控制器中?以前,我遇到了一个未定义的方法错误。
注意:我确信有一种方法可以更好地编写代码。我也很感激你的帮助。
答案 0 :(得分:2)
#app/models/patient.rb
class Patient < ActiveRecord::Base
protected
def name=(value)
mod_name = []
value.split.each do |n|
n.split("")
type = n[0] ? "up" : "down"
n.send("#{type}case")
mod_name.push(n)
end
@name = mod_name.join
end
end
#app/controllers/patients_controller.rb
class PatientsController < ApplicationController
def create
@patient = Patient.new patient_params
@patient.save ? redirect_to(patients_path) : render(:new)
end
private
def patient_params
params.require(:patient).permit(:name)
end
end
您正在尝试覆盖setter方法,可以使用上述代码完成。效率更高,更方便。
我创建了以下方法
既然你是新手,请让我解释一下。
请务必注意 您使用此方法。
您目前已将其置于模型中,这意味着您必须调用它来操纵使用该模型创建的任何对象的某些属性/功能。
-
模型 - 在Rails中 - 构建填充应用的objects。 Ruby是object orientated language,这意味着程序的每个元素都应该在某种程度上围绕数据对象。
正如您在上面所看到的,在系统中构建对象的方法实际上是关于调用 classes 。这些类包含方法,可以在类级别(IE通过方法调用类)或实例级别(IE)调用在已经调用的对象上调用方法。)
这是您从"class" methods (Model.method
) and "instance" methods (@model.method
)获得的地方:
#app/models/patient.rb
class Patient < ActiveRecord::Base
def explode
#this is an instance method
puts "Instance Explode"
end
def self.explode
#this is a class method
puts "Exploded"
end
end
因此,您可以拨打以下电话:
@patient = Patient.find params[:id]
@patient.explode #-> "Instance explode"
Patient.explode #-> "Exploded"
-
这很重要,因为它为您提供了一个严格的框架,您应该在模型中使用方法。
它解释了为什么你有控制器&amp; helpers ,并允许您制定构建应用程序的最佳方法,以便充分利用最少的代码。
例如......
您使用@patient.name = params[:params][:name].name_fix
不正确。
这是错误的,因为您在与您的模型完全无关的数据上调用了实例方法 .name_fix
。如果你想在这样的一般意义上使用.name_fix
,你可能会使用helper
:
#app/helpers/patients_helper.rb
class PatientsHelper
def name_fix value
# stuff here
end
end
#app/controllers/patients_controller.rb
class PatientsController < ApplicationController
def create
@patient.name = name_fix params[:patient][:name]
end
end
由于您使用该方法填充模型的.name
属性,因此覆盖name=
setter是有意义的。这不仅会提供额外的功能,而且比任何其他方式都更加顺畅和高效。
答案 1 :(得分:0)
直接调用的方法最好放在Controller中(如果您认为多个控制器可能想要使用它,则放在ApplicationController
中)。
这些是像
这样的方法# app/controllers/my_controller.rb
def foo(bar)
# do something here
end
def create
id = params[:id]
value = foo(id)
end
如果你想要一个链式方法,它可以作为你调用它的任何属性的属性方法。这些是模型工作方式的特征 - 您拥有主模型,并在该模型的实例上调用属性或方法。
# app/models/my_model.rb
def full_name
first_name + " " + last_name
end
# app/controller/my_controller.rb
def create
id = params[:id]
model = MyModel.find(id)
full_name = model.full_name
end
在您的情况下,您想要name_fix
致电params[:params][:name]
返回的任何内容,即(我猜测)String
。
您有两个选择
修改String
类以定义名为name_fix
的方法。我强烈推荐此。它的电话&#34; monkeypatching&#34;并且不应该没有充分的理由。只是让你知道你可以在某些情况下这样做。
使用控制器中的直接方法或ApplicationController
,如上面的第一个示例。
@ patient.name = name_fix(params [:params] [:name])
编辑:关于更好地编写代码的请求......在一个答案中难以教授或传达。我说在那里阅读一些开源项目,看看人们如何编写Ruby以及一些用于清理代码的常用习惯用法。为了帮助您入门,请按照以下方式重新编写代码
def create
@patient = Patient.new(params[:patient])
# 1. Be descriptive with your method names. `name_fix` is vague
# 2. Why is `:name` nested under another `[:params]` hash?
@patient.name = capitalize_name(params[:name])
if @patient.save
# 1. I think `patient_path` has to be singular
# 2. It needs a `Patient` object to know how to construct the URL
# e.g. `/patients/:id`
redirect_to patient_path(@patient)
else
render :new
end
end
def capitalize_name(full_name)
# Example: julio jones
#
# 1. `split` produces an array => ["julio", "jones"]
# 2. `map` applies a function (`capitalize`) to each element
# => ["Julio", "Jones"]
# 3. `join(" ")` rejoins it => "Julio Jones"
full_name.split.map(&:capitalize).join(" ")
end
答案 2 :(得分:0)
假设您使用name_fix
方法的目标只是将每个名称的第一个字母大写,您可以将name
作为参数传递并将其作为私有方法存储在Controller上:
# app/controllers/patient_controller.rb
private
def name_fix(name)
name.split.map(&:capitalize).join(" ")
end
然后你可以做
@patient.name = name_fix(params[:params][:name])
在create
方法中。
或者,您可以将此方法存储在模型中:
# app/models/patient.rb
def self.name_fix(name)
name.split.map(&:capitalize).join(" ")
end
然后你可以在控制器中执行此操作:
@patient.name = Patient.name_fix(params[:params][:name])
我还建议您将name_fix
方法重命名为capitalize_name
。
答案 3 :(得分:0)
更新您的创建方法,如下所示
def create
@patient = Patient.new(params[:patient])
@patient.name = params[:params][:name]
@patient = @patient.name_fix
if @patient.save
redirect_to patients_path
else
render :new
end
end
它应该有用。