Ruby on Rails - 创建和使用自定义方法

时间:2015-10-16 05:18:24

标签: ruby-on-rails ruby

我对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

我该如何完成这项工作?此方法是否位于我的模型或控制器中?以前,我遇到了一个未定义的方法错误。

注意:我确信有一种方法可以更好地编写代码。我也很感激你的帮助。

4 个答案:

答案 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,这意味着程序的每个元素都应该在某种程度上围绕数据对象。

enter image description here

正如您在上面所看到的,在系统中构建对象的方法实际上是关于调用 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

您有两个选择

  1. 修改String类以定义名为name_fix的方法。我强烈推荐此。它的电话&#34; monkeypatching&#34;并且不应该没有充分的理由。只是让你知道你可以在某些情况下这样做。

  2. 使用控制器中的直接方法或ApplicationController,如上面的第一个示例。

    @ patient.name = name_fix(params [:params] [:name])

  3. 编辑:关于更好地编写代码的请求......在一个答案中难以教授或传达。我说在那里阅读一些开源项目,看看人们如何编写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

它应该有用。