0

最初に、一見簡単な質問で申し訳ありませんが、Rails、Ruby、およびプログラミングに不慣れな私は、そこにある「Rails の新機能」チュートリアルを使い果たしたように感じます。

これが私が反対しているものです。

「has_many :through => :company_reps」関係を持つユーザー モデルと機関モデルがあります。

ユーザーには基本的なフィールド (名前、電子メール、パスワード) があります (私は devise を使用ています)

インスティテューションには多くのフィールドがありますが、関連するフィールドは次のとおりです (client = boolean, lead = boolean, demo_date = date/time) さらに複雑にするために、各インスティテューションには 1 人または 2 人のユーザーがいる可能性がありますが、ほとんどの場合、1 人しかいません。

ユーザー向けのコンテストを開催しており、demo_date フィールドと client フィールドに基づいて各ユーザーにポイントを付与する必要があります。

最初に、クライアントである機関に関連する 10 ポイントを各ユーザーに与える必要があります。ただし、その機関に 2 人のユーザーがいる場合は、その 2 人のユーザーにそれぞれ 5 ポイントを与える必要があります。

次に、デモ日が 2012 年 2 月以降の機関に関連するすべてのユーザーに 1 ポイントを与える必要があります。

Ruby 1.9.2、Rails 3.2.8、および MySQL を使用しています

  • では、どうすればこれを達成できますか?
  • ポイントを保存するために新しいテーブルとモデルを作成する必要がありますか? その場合、計算を保存するにはどうすればよいですか?
  • すべての計算をユーザー モデルまたは機関モデルに入れる必要がありますか?

いつも助けてくれてありがとう。

MySQL 機関情報

CREATE TABLE `institutions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `state_id` int(11) DEFAULT NULL,
  `company` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `clientdate` datetime DEFAULT NULL,
  `street` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `city` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `zip` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `source` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `source2` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
  `demodate1` datetime DEFAULT NULL,
  `demodate2` datetime DEFAULT NULL,
  `demodate3` datetime DEFAULT NULL,
  `client` tinyint(1) DEFAULT NULL,
  `prospect` tinyint(1) DEFAULT NULL,
  `alead` tinyint(1) DEFAULT NULL,
  `notcontacted` tinyint(1) DEFAULT NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7805 DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci; 

機関モデル

class Institution < ActiveRecord::Base
  attr_accessible :company, :phone, :assets, :clientdate, :street, :city, :state_id, :zip, :source, :source2, :demodate1, :demodate2, :demodate3, :client, :prospect, :alead, :notcontacted
  belongs_to :state
  has_many :users, :through => :company_reps
  has_many :company_reps

end

ユーザーモデル

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me, :first_name, :last_name
  # attr_accessible :title, :body

  has_many :states, :through => :rep_areas
  has_many :institutions, :through => :company_reps
  has_many :rep_areas
  has_many :company_reps

  def name 
    first_name + " " + last_name
  end


end

会社の担当者のモデル

class CompanyRep < ActiveRecord::Base
  belongs_to :user
  belongs_to :institution
end
4

2 に答える 2

2

更新(私の最初の試みは間違って仮定していたのでUser has_one :institution

最も簡単なオプションは、Institutionモデルで基本的な計算を行って機関が「価値がある」ポイント数を確立し、その値を合計してユーザーのポイントを計算することです。

# Institution
def points
  points_for_client + points_for_demo_date
end

private

def points_for_client
  if client?
    10 / users.count
  else
    0
  end
end

def points_for_demo_date
  if demo_date.present? && demo_date >= Date.new(2012, 3, 1)
    1
  else
    0
  end
end

if必要に応じて、これらのステートメントを三項演算子を使用して 1 行にまとめることができることに注意してください? :。また、「2月以降」とは「3月1日以降」を意味するものとしました。

nil のチェックdemo_dateも好みの問題です。からお選びください

# Verbose, but IMO intention-revealing
demo_date.present? && demo_date >= Date.new(...)

# Perhaps more idiomatic, since nil is falsy
demo_date && demo_date >= Date.new(...)

# Take advantage of the fact that >= is just another method
# Concise, but I think it's a bit yuk!
demo_date.try :>=, Date.new(...)

各機関が特定のポイント数に値するので、それらを合計するのは非常に簡単です。

# User
def points
  institutions.inject(0) {|sum, institution| sum + institution.points }
end

慣れていない場合は、ドキュメントをinject確認してください。これは気の利いた小さな方法です。

パフォーマンスに関する限り、これは最適ではありません。基本的な改善は、結果をメモすることです。

# Institution
def points
  @points ||= points_for_client + points_for_demo_date
end

# User
def points
  @points ||= institutions.inject ...
end

同じリクエストでさらに を呼び出してpointsも値が再計算されないようにします。オブジェクトがまだ生きている間にclientanddemo_dateが変更されない限り、それは問題ありません。User

some_user.points   #=> 0
some_user.institution.client = true
some_user.points   #=> 0 ... oops

オブジェクトは次のUserリクエストで再作成されるため、これは問題にならない可能性があります (これらのフィールドがどのように変化するかによって異なります)。

代わりに元のバージョンをメソッドとして使用して、pointsフィールドを追加Userしてデータベースに値を保存することもできます。update_points

def update_points
  self.points = institutions.inject ...
end

ただし、値をいつ再計算するかが問題になります。

私の提案は、できるだけシンプルに保ち、時期尚早の最適化を避けることです。これは比較的単純な計算であるため、膨大な数のユーザーや機関、または多くのリクエストが進行していない限り、大きなパフォーマンスの問題にはなりません。

于 2012-10-24T17:20:45.400 に答える
0

ポイントは s に蓄積されるため、蓄積したポイント数を返すクラスにUserメソッド呼び出しを追加することは理にかなっているように思われます。User

まず、呼び出されるたびに合計ポイントを計算するメソッドを作成し、計算が正しいことを確認するための単体テストを行います。最初は結果を保存しません。オブジェクトの数、ポイントを計算する必要がある頻度などによっては、保存する必要がない場合もあります。

于 2012-10-24T16:13:33.560 に答える