9

私の Rails アプリでは、ビジネスを作成するときに、次のフィールドを持つフォームがあります。

   <%= check_box_tag(:default_company) %> 
   <%= label_tag(:default_company, "Set Company as Default") %>

基本的に、ビジネスを作成するときに、このボックスをオンにした場合、次のコードのようなものを実行する必要があります。

def set_default_company(company, user)
  exists = DefaultCompany.find(user.id)
  if exists
    exists.update_attributes(company: company)
  else  
    DefaultCompany.create(company: company, user: user)
  end
end

学習中、私は通常、コントローラーでそのようなことを行いますが、ベストプラクティスに従ってファットモデル、スキニーコントローラーを使用しようとしているため、次のようなロジックを使用したいと考えています:

def create
  @company = Company.new(params[:company])

  if @company.save
    if params[:default_company]
      Company.set_default_company(@company.id, current_user.id,)
    end
    flash[:notice] = "Company was successfully created."
    redirect_to @company
  else
    redirect_to new_company_path
  end
end

ここで、 を呼び出すためにクラス メソッドとインスタンス メソッドのどちらを使用するかについて混乱していますset_default_company。どちらも機能するように見えますが、どちらにもメリットはありません。

どのメソッドを使用するかについての情報を提供することに加えて、誰かがそれをクラス メソッドとインスタンス メソッドとして記述する簡単な実装を示すことができれば、その理由をよりよく理解できるかもしれません。

これが私がそれらを書く方法です:

def self.set_default_company(company, user)
  # Logic here
end

def set_default_company(company, user)
  # Logic here
end

そのように書いても、どちらにもメリットはありません。

4

4 に答える 4

20

As their name suggests, instance methods on a model should be used for logic/operations that relate to a specific instance of a user (the one on which the method is called.) So you could think of setting the default company for a user as an instance method on User. Class methods are for things which don't operate on an individual instance of a model or for cases where you don't have the instance available to you. e.g. you might have a class method to tidy up your database such as User.purge_expired_users which would not apply to an individual user object.

e.g.

class User
  def set_default_company(company)
    exists = DefaultCompany.find(self.id)
    if exists
      exists.update_attributes(company: company)
    else  
      DefaultCompany.create(company: company, user: self)
    end
  end
end

then your controller method would look like:

def create
  @company = Company.new(params[:company])

  if @company.save
    if params[:default_company]
      current_user.set_default_company @company
    end
    flash[:notice] = "Company was successfully created."
    redirect_to @company
  else
    redirect_to new_company_path
  end
end

Alternatively, you could think of the relationship from the other perspective and put an instance method on Company e.g. company.set_as_default_for(user).

于 2012-07-25T18:05:31.577 に答える
4

で実際にset_default_companyインスタンスメソッドを作成しますUser。AUserにはデフォルトがありますCompanyCompanyデフォルトのユーザーが必要なのはなぜですか?

class User
    def set_default_company(company)
        exists = DefaultCompany.find(id)
        if exists
            exists.update_attributes(company: company)
        else  
            DefaultCompany.create(company: company, user: self)
         end
     end
 end
于 2012-07-25T18:03:46.067 に答える
2

私の意見ではclass method、問題のメソッドがインスタンス化されたすべてのオブジェクト間で非常に一般的な情報/動作を表す ifを常に作成しinstance methodsます。これは、インスタンス化されたオブジェクトの特定のアクションに似ていると思われる場合に使用する とは異なります。

しかし、それは私の視点です。

于 2012-07-25T18:10:11.423 に答える
1

いくつかのこと: DefaultCompany 用に別のテーブルがありますか? これは、会社のテーブルのブール値フラグであるように思われます。

次に、企業とユーザーの関係性は?もしそうなら、それを行うための最良の方法は

ユーザーモデルでは

def set_default_company(company)
  self.companies.each do |c|
    c.update_attributes(:default => false)
  end
  company.update_attributes(:default => true)
end

または会社のモデルで

def set_as_default
  update_attributes(:default_company => true)
end
于 2012-07-25T18:09:09.177 に答える