1

私は奇妙なエラーに直面しています。誰でもこの理由を説明できますか..

Site、Settings、および Experiences というモデルがあります。

設定とエクスペリエンスにはデータベース列「ビット」があります

私のサイトモデルには、このコードがあります

  def populate_experiences_bit_set
    self.experiences.map(&:bit).inject(0, :|)
  end

  def populate_settings_bit_set
    self.settings.map(&:bit).inject(0, :|)
  end

2_28.rake という私の rake ファイルには、bitというメソッドがあります。

 def bit(klass)
    current_class = klass.find(:all)
    if current_class.count == 0
      return 1
    else
      return (current_class.last.bit * 2)
    end
  end

このメソッドは、同じ rake ファイル内の rake タスク 'get_value' の 1 つで使用されます。

また、同じファイル内の create_sites_report_data と呼ばれる別の rake タスクには、次の行があります。

site.populate_experiences_bit_set

rake タスクを実行すると

rake releases:2.28:create_sites_report_data

エラーが表示されます

" プライベート メソッド /Users/rakeshshetty/.rvm/gems/ruby-1.9.2-p290/gems/activerecord-2.3.5/lib/active_record/attribute_methods.rb:236:in `method_missing' を呼び出そうとしています "

In console, this works fine 

>> s = Site/364
=> #<Site id: 364, name: "1 Field Ambulance - Detachment Wainwright", type: "Site", created_at: "2009-12-29 16:53:58", updated_at: "2009-12-29 16:53:58", short_name: "1 Field Am", self_updated_at: nil, last_updater_id: nil, vfp_id: "2BL0NFMI1", dup_reference_id: nil, field_id: nil, marked_as_deleted: false>
>> s.experiences.map(&:bit).inject(0, :|)
=> 0
>> s.settings.map(&:bit).inject(0, :|)
=> 64

2_28.rake ファイルのメソッド名を bit から bit_x に置き換えました Rake は正常に動作しました

blsi1181a:cpi_2.24 rakeshshetty$ rails -v 
Rails 2.3.5 
blsi1181a:cpi_2.24 rakeshshetty$ ruby -v 
ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.3.0]

私の質問は、設定とエクスペリエンスのフィールドです。rake メソッド関数 bit() をどのように呼び出しますか? このレーキ ファイルは、アプリケーションのロード後にロードされますか?

4

1 に答える 1

2

これが問題だと思います:

モデルにはメソッドがなくbit、「メソッドが見つからない」アプローチで作成されます (つまり、オブジェクトで存在しないメソッドを呼び出すと、その method_missing メソッドが呼び出され、デフォルトで例外が発生します)。

ActiveRecord は、関連するテーブルの列のメソッドを設定するために、不足しているメソッドを使用します (つまり、

Site.new.bit -> the method does not exist -> method_missing -> 
  is there a column called 'bit'? -> yes -> create the method bit with this code

bitこれで、オブジェクト レベルでメソッドが作成されました。おそらくそれmethod_missingは ActiveRecord のアプローチを破っています:

Site.new.bit -> the method exists -> call that method

資力:


編集:より深い分析の後

ActiveRecord のソース (エラーの近く) を見ると、次のようになります。

def method_missing(method_id, *args, &block)
  method_name = method_id.to_s

  if self.class.private_method_defined?(method_name)
    raise NoMethodError.new("Attempt to call private method", method_name, args)
  end

  [...]

次に、次のタスクを試してください。

namespace :rake_test do

  desc 'With bit method'
  task :with => :environment do

    def bit(klass)
      # Implementation
    end

    puts Object.private_method_defined?("bit")
    puts Settings.private_method_defined?("bit")

  end

  desc 'Without bit method'
  task :without => :environment do

    puts Object.private_method_defined?("bit")
    puts Settings.private_method_defined?("bit")

  end

end

それらを実行しましょう:

rake rake_test:with ; rake rake_test:without

出力:

true
true
false
false

メソッドを定義するbitと、オブジェクト コンテキストになります (これは rake タスク ファイルだけでなく、すべての ruby​​ スクリプト ファイルにも当てはまります)。したがって、Object.bitメソッドを定義します。bitRails のソース コードからわかるように、モデル メソッドを定義する前にが存在するかどうかを確認し、存在Model.methodする場合は例外を発生させます。

(すべての標準クラスと同様に)のSettingsクラス サブクラスであるため、定義によって問題が発生します。Objectbit

于 2012-06-15T14:29:33.383 に答える