2011-05-13 19 views
17

दोनों के साथ रेल ऑडिट सिस्टम मेरे पास ActiveRecord और ActiveResource दोनों मॉडल के साथ एक विशाल प्रोजेक्ट है। मुझे इन मॉडलों के साथ उपयोगकर्ता गतिविधि के लॉगिंग को लागू करने और मॉडल विशेषताओं के परिवर्तन लॉग इन करने की आवश्यकता है (ऑब्जेक्ट स्टेटस को सहेजें या ऐसा कुछ भी)। परिवर्तन उपयोगकर्ताओं या क्रॉन रेक कार्यों द्वारा किए जा सकते हैं।ActiveResource और ActiveRecord

मैं उस तिथि के आधार किसी भी डेटा खोज करने के लिए संभावना, किसी भी क्षेत्र

आदि

भी अच्छा अंतिम गतिविधि के साथ पठनीय संदेशों उत्पन्न करने के लिए किया जाएगा, उदाहरण के

  • उपयोगकर्ता बॉब बदलाव के लिए होना आवश्यक है 2011-08-12 08:12
  • स्टाफ जेफ पर करने के लिए * और ** को ईमेल अपने पासवर्ड नई बराबर जोड़ा tner: कंपनी का नाम 2011-08-12 08:13
  • व्यवस्थापक जैक उत्पाद हटा दिया गया: 2011-09-12 11:11
  • क्लाइंट सैम ने नई सेवा का आदेश दिया: सेवा का नाम 2011-09-12 11 : 12

क्या कोई इस तरह के लॉगिंग को लागू करता है? विचार? सलाह?

क्या मुझे रत्नों का उपयोग करना चाहिए या क्या मैं पर्यवेक्षकों के साथ सभी तर्कों को मॉडल बदल नहीं सकता?


मैं मणि https://github.com/airblade/paper_trail पसंद आया किसी को भी कह सकते हैं मैं इसे कैसे activeresource के साथ काम कर सकते हैं?

+0

आप ही डेटा या बदलने या स्कीमा के बदलते मतलब है: यह लिंक है जिसे आप मदद कर सकता है है? ये दो अलग-अलग चीजें हैं। मेरा जवाब डेटा के लिए लक्षित है ... – lzap

+0

डेटा बदल रहा है, स्कीमा – Fivell

उत्तर

1

acts_as_audited मणि आप के लिए अच्छी तरह से काम करना चाहिए:
https://github.com/collectiveidea/acts_as_audited

और जहाँ तक ActiveResource माना जाता है, यह भी कुछ अन्य आवेदन में एक मॉडल हो जाएगा। आप सर्वर के पक्ष में मणि का उपयोग कर सकते हैं, और आपको इसे क्लाइंट साइड पर ऑडिट करने की आवश्यकता नहीं है। ActiveResource का उपयोग कर सभी सीआरयूडी ऑपरेशंस अंततः ActiveRecord (सर्वर पक्ष पर) पर CRUD संचालन में अनुवाद करेंगे।

तो शायद आपको इसे दूरी से देखने की आवश्यकता है, और एक ही समाधान दोनों मामलों में, लेकिन विभिन्न स्थानों पर लागू होगा।

+0

यदि ऑडिटिंग सर्वर की ओर (Activeresource) और क्लाइंट साइड (ActiveRecord) दोनों पर होगा, तो मैं कैसे खोज सकता हूं, आखिरी गतिविधि दिखा सकता हूं .. आदि? मुझे लगता है कि – Fivell

+0

सभी गतिविधियों के लिए मुझे एक स्टोरेज की आवश्यकता है, यह इस बात पर निर्भर करता है कि आप किस जानकारी को देखना चाहते हैं। मैंने मणि का उपयोग नहीं किया है, लेकिन मुझे यकीन है कि यह एक टेबल में ऑडिट जानकारी संग्रहीत करेगा। यदि आपको सर्वर की तरफ इसकी आवश्यकता है तो आप हमेशा एक मॉडल बना सकते हैं और ActiveRecord का उपयोग करके इसका उपयोग कर सकते हैं, और यदि आपको क्लाइंट साइड पर इसकी आवश्यकता है तो आप ऑडिट जानकारी तक पहुंचने के लिए एक और ActiveResource ऑब्जेक्ट बना सकते हैं। आपको बस यह देखने की आवश्यकता है कि डेटा कहां है रहना। यदि यह एक ही स्थान पर है तो आपको ActiveRecord का उपयोग करना चाहिए और यदि नहीं, तो दूरस्थ रूप से जानकारी तक पहुंचने के लिए ActiveResource का उपयोग करें। –

+0

मुझे क्लाइंट डेटाबेस में ऑडिटिंग जानकारी स्टोर करने की आवश्यकता है, इसके बिना ActiveResource या ActiveRecord है, मेरे पास अन्य एप्लिकेशन के स्रोत कोड को बदलने की कोई संभावना नहीं है जिसे मैं ActiveResource – Fivell

4

आप

https://github.com/collectiveidea/acts_as_audited

कुछ खुला स्रोत परियोजनाओं के लिए देख रहे हैं का उपयोग मुझे लगता है कि प्लगइन लाल खान रूप में अच्छी तरह के रूप में फोरमैन

संपादित करें: दुर्भाग्य से यह केवल ActiveRecord ही सक्रिय संसाधन नहीं कर सकता है।

+0

धन्यवाद नहीं, लेकिन क्या यह Activeresource के साथ काम करता है? – Fivell

+0

मुझे ऐसा नहीं लगता है :-( – lzap

+0

हाँ मुझे करने के लिए = (कुछ अन्य विचार? – Fivell

3

https://github.com/collectiveidea/acts_as_audited

और

https://github.com/airblade/paper_trail

ActiveRecord केवल, लेकिन ActiveRecord के ज्यादा के बाद से ActiveModel को निकाला गया है के लिए दोनों महान समाधान कर रहे हैं, यह विस्तार करने के लिए या तो के रूप में ActiveResource समर्थन करने के लिए उचित होने की संभावना है ठीक है, कम से कम केवल पढ़ने के लिए समर्थन के लिए। मैंने गिथब नेटवर्क ग्राफ़ों को देखा और चारों ओर घूमते हुए देखा और ऐसे समाधान का कोई भी सतत विकास प्रतीत नहीं होता है, फिर भी मुझे उम्मीद है कि स्क्रैच से शुरू होने से इन दो प्लगइनों में से एक के शीर्ष पर लागू करना आसान होगा। paper_trail अधिक सक्रिय विकास के तहत प्रतीत होता है और कुछ रेल 3.1 के लिए काम करता है, इसलिए यह रेल इंटर्नल्स के साथ अधिक अद्यतित हो सकता है और विस्तार करना आसान हो सकता है, लेकिन यह सिर्फ एक आंत वृत्ति है- मैं आंतरिक के साथ परिचित नहीं हूं। इस railscast पर

+0

धन्यवाद – Fivell

4

Fivell, मैं सिर्फ इस सवाल को देखा और इस शाम परिवर्तन ऊपर काम करने के लिए इससे पहले कि इनाम की समय सीमा समाप्त समय नहीं है, तो मैं दे देंगे आप मेरे ऑडिटिंग कोड जो ActiveRecord के साथ काम करते हैं और ActiveResource के साथ काम करना चाहिए, शायद कुछ tweaks के साथ (मैं अक्सर एआरएस का उपयोग करने के लिए पर्याप्त नहीं है)। मुझे पता है कि हमारे द्वारा उपयोग किए जाने वाले कॉलबैक हैं, लेकिन मुझे यकीन नहीं है कि अगर एआरएस में ActiveRecord की गंदे विशेषता changes ट्रैकिंग है।

यह कोड जेएसओएन के रूप में संग्रहीत परिवर्तनों के साथ सभी मॉडलों (ऑडिट लॉग मॉडल और आपके द्वारा निर्दिष्ट किसी भी अन्य अपवादों को छोड़कर) पर प्रत्येक CREATE/UPDATE/DELETE लॉग करता है। एक साफ बैकट्रैक भी संग्रहीत किया जाता है ताकि आप यह निर्धारित कर सकें कि किस कोड ने परिवर्तन किया है (यह आपके एमवीसी के साथ-साथ रेक कार्य और कंसोल उपयोग में किसी भी बिंदु को कैप्चर करता है)।

यह कोड कंसोल उपयोग, रेक कार्य, और http अनुरोधों के लिए काम करता है, हालांकि आमतौर पर केवल अंतिम उपयोगकर्ता वर्तमान उपयोगकर्ता को लॉग करता है। (अगर मुझे सही याद है, तो ActiveRecord पर्यवेक्षक जो इसे प्रतिस्थापित करता है, रेक रेक या कंसोल में काम नहीं करता है।) ओह, यह कोड रेल 2.3 ऐप से आता है - मेरे पास कुछ रेल 3 ऐप्स हैं, लेकिन मुझे इस तरह की आवश्यकता नहीं है अभी तक उनके लिए लेखा परीक्षा का।

मेरे पास ऐसा कोड नहीं है जो इस जानकारी का एक अच्छा प्रदर्शन बनाता है (जब हमें किसी समस्या को देखने की आवश्यकता होती है तो हम केवल डेटा में खोदते हैं), लेकिन चूंकि जेएसओएन के रूप में परिवर्तनों को संग्रहीत किया जाता है, यह काफी सरल होना चाहिए।

Class User < ActiveRecord::Base 
    cattr_accessor :current 
    ... 
end 

वर्तमान उपयोगकर्ता (ताकि तरह प्रत्येक अनुरोध के लिए आवेदन नियंत्रक में स्थापित है और ऐसा नहीं करता है:

सबसे पहले, हम User.current वर्तमान उपयोगकर्ता तो यह हर जगह उपलब्ध है, app/models/user.rb में तो स्टोर संगामिति समस्याओं का कारण):

def current_user 
    User.current = session[:user_id] ? User.find_by_id(session[:user_id]) : nil 
end 

आप अपने रेक कार्यों में User.current सेट कर सकते हैं अगर यह समझ बना दिया।

# == Schema Information 
# 
# Table name: audit_log_entries 
# 
# id   :integer   not null, primary key 
# class_name :string(255) 
# entity_id :integer 
# user_id :integer 
# action  :string(255) 
# data  :text 
# call_chain :text 
# created_at :datetime 
# updated_at :datetime 
# 

class AuditLogEntry < ActiveRecord::Base 
    IgnoreClassesRegEx = /^ActiveRecord::Acts::Versioned|ActiveRecord.*::Session|Session|Sequence|SchemaMigration|CronRun|CronRunMessage|FontMetric$/ 
    belongs_to :user 

    def entity (reload = false) 
    @entity = nil if reload 
    begin 
     @entity ||= Kernel.const_get(class_name).find_by_id(entity_id) 
    rescue 
     nil 
    end 
    end 

    def call_chain 
    return if call_chain_before_type_cast.blank? 
    if call_chain_before_type_cast.instance_of?(Array) 
     call_chain_before_type_cast 
    else 
     JSON.parse(call_chain_before_type_cast) 
    end 
    end 
    def data 
    return if data_before_type_cast.blank? 
    if data_before_type_cast.instance_of?(Hash) 
     data_before_type_cast 
    else 
     JSON.parse(data_before_type_cast) 
    end 
    end 

    def self.debug_entity(class_name, entity_id) 
    require 'fastercsv' 
    FasterCSV.generate do |csv| 
     csv << %w[class_name entity_id date action first_name last_name data] 
     find_all_by_class_name_and_entity_id(class_name, entity_id, 
              :order => 'created_at').each do |a| 
     csv << [a.class_name, a.entity_id, a.created_at, a.action, 
      (a.user && a.user.first_name), (a.user && a.user.last_name), a.data] 
     end 
    end 
    end 
end 

अगला हम करने के लिए ActiveRecord::Base करने के लिए कुछ तरीके जोड़: -

इसके बाद, हम लेखा परीक्षा की जानकारी app/models/audit_log_entry.rb स्टोर करने के लिए मॉडल को परिभाषित आप अनुकूलित करने के लिए IgnoreClassesRegEx किसी भी मॉडल आप लेखा परीक्षित नहीं करना चाहती फिट करने के लिए चाहता हूँ लेखा परीक्षा काम करते हैं। आप audit_log_clean_backtrace विधि को देखना और अपनी आवश्यकताओं के लिए संशोधित करना चाहते हैं।(। Fwiw, हम अतिरिक्त मौजूदा वर्गों के लिए lib/extensions/*.rb जो एक प्रारंभकर्ता में लोड किए गए हैं में डाल) lib/extensions/active_record.rb में: अंत में

class ActiveRecord::Base 
    cattr_accessor :audit_log_backtrace_cleaner 
    after_create :audit_log_on_create 
    before_update :save_audit_log_update_diff 
    after_update :audit_log_on_update 
    after_destroy :audit_log_on_destroy 
    def audit_log_on_create 
    return if self.class.name =~ /AuditLogEntry/ 
    return if self.class.name =~ AuditLogEntry::IgnoreClassesRegEx 
    audit_log_create 'CREATE', self, caller 
    end 
    def save_audit_log_update_diff 
    @audit_log_update_diff = changes.reject{ |k,v| 'updated_at' == k } 
    end 
    def audit_log_on_update 
    return if self.class.name =~ AuditLogEntry::IgnoreClassesRegEx 
    return if @audit_log_update_diff.empty? 
    audit_log_create 'UPDATE', @audit_log_update_diff, caller 
    end 
    def audit_log_on_destroy 
    return if self.class.name =~ AuditLogEntry::IgnoreClassesRegEx 
    audit_log_create 'DESTROY', self, caller 
    end 
    def audit_log_create (action, data, call_chain) 
    AuditLogEntry.create :user  => User.current, 
         :action  => action, 
         :class_name => self.class.name, 
         :entity_id => id, 
         :data  => data.to_json, 
         :call_chain => audit_log_clean_backtrace(call_chain).to_json 
    end 
    def audit_log_clean_backtrace (backtrace) 
    if !ActiveRecord::Base.audit_log_backtrace_cleaner 
     ActiveRecord::Base.audit_log_backtrace_cleaner = ActiveSupport::BacktraceCleaner.new 
     ActiveRecord::Base.audit_log_backtrace_cleaner.add_silencer { |line| line =~ /\/lib\/rake\.rb/ } 
     ActiveRecord::Base.audit_log_backtrace_cleaner.add_silencer { |line| line =~ /\/bin\/rake/ } 
     ActiveRecord::Base.audit_log_backtrace_cleaner.add_silencer { |line| line =~ /\/lib\/(action_controller|active_(support|record)|hoptoad_notifier|phusion_passenger|rack|ruby|sass)\// } 
     ActiveRecord::Base.audit_log_backtrace_cleaner.add_filter { |line| line.gsub(RAILS_ROOT, '') } 
    end 
    ActiveRecord::Base.audit_log_backtrace_cleaner.clean backtrace 
    end 
end 

, यहाँ परीक्षण हम इस पर कर रहे हैं - आप वास्तविक परीक्षा कार्यों को संशोधित करना होगा बेशक। test/integration/audit_log_test.rb

require File.dirname(__FILE__) + '/../test_helper' 

class AuditLogTest < ActionController::IntegrationTest 
    def setup 
    end 

    def test_audit_log 
    u = users(:manager) 
    log_in u 
    a = Alert.first :order => 'id DESC' 
    visit 'alerts/new' 
    fill_in 'alert_note' 
    click_button 'Send Alert' 
    a = Alert.first :order => 'id DESC', :conditions => ['id > ?', a ? a.id : 0] 
    ale = AuditLogEntry.first :conditions => {:class_name => 'Alert', :entity_id => a.id } 
    assert_equal 'Alert', ale.class_name 
    assert_equal 'CREATE', ale.action 
    end 

private 

    def log_in (user, password = 'test', initial_url = home_path) 
    visit initial_url 
    assert_contain 'I forgot my password' 
    fill_in 'email', :with => user.email 
    fill_in 'password', :with => password 
    click_button 'Log In' 
    end 

    def log_out 
    visit logout_path 
    assert_contain 'I forgot my password' 
    end 
end 

और test/unit/audit_log_entry_test.rb:

# == Schema Information 
# 
# Table name: audit_log_entries 
# 
# id   :integer   not null, primary key 
# class_name :string(255) 
# action  :string(255) 
# data  :text 
# user_id :integer 
# created_at :datetime 
# updated_at :datetime 
# entity_id :integer 
# call_chain :text 
# 

require File.dirname(__FILE__) + '/../test_helper' 

class AuditLogEntryTest < ActiveSupport::TestCase 
    test 'should handle create update and delete' do 
    record = Alert.new :note => 'Test Alert' 
    assert_difference 'Alert.count' do 
     assert_difference 'AuditLogEntry.count' do 
     record.save 
     ale = AuditLogEntry.first :order => 'created_at DESC' 
     assert ale 
     assert_equal 'CREATE', ale.action, 'AuditLogEntry.action should be CREATE' 
     assert_equal record.class.name, ale.class_name, 'AuditLogEntry.class_name should match record.class.name' 
     assert_equal record.id, ale.entity_id, 'AuditLogEntry.entity_id should match record.id' 
     end 
    end 
    assert_difference 'AuditLogEntry.count' do 
     record.update_attribute 'note', 'Test Update' 
     ale = AuditLogEntry.first :order => 'created_at DESC' 
     expected_data = {'note' => ['Test Alert', 'Test Update']} 
     assert ale 
     assert_equal 'UPDATE', ale.action, 'AuditLogEntry.action should be UPDATE' 
     assert_equal expected_data, ale.data 
     assert_equal record.class.name, ale.class_name, 'AuditLogEntry.class_name should match record.class.name' 
     assert_equal record.id, ale.entity_id, 'AuditLogEntry.entity_id should match record.id' 
    end 
    assert_difference 'AuditLogEntry.count' do 
     record.destroy 
     ale = AuditLogEntry.first :order => 'created_at DESC' 
     assert ale 
     assert_equal 'DESTROY', ale.action, 'AuditLogEntry.action should be CREATE' 
     assert_equal record.class.name, ale.class_name, 'AuditLogEntry.class_name should match record.class.name' 
     assert_equal record.id, ale.entity_id, 'AuditLogEntry.entity_id should match record.id' 
     assert_nil Alert.find_by_id(record.id), 'Alert should be deleted' 
    end 
    end 

    test 'should not log AuditLogEntry create entry and block on update and delete' do 
    record = Alert.new :note => 'Test Alert' 
    assert_difference 'Alert.count' do 
     assert_difference 'AuditLogEntry.count' do 
     record.save 
     end 
    end 
    ale = AuditLogEntry.first :order => 'created_at DESC' 
    assert_equal 'CREATE', ale.action, 'AuditLogEntry.action should be CREATE' 
    assert_equal record.class.name, ale.class_name, 'AuditLogEntry.class_name should match record.class.name' 
    assert_equal record.id, ale.entity_id, 'AuditLogEntry.entity_id should match record.id' 
    assert_nil AuditLogEntry.first(:conditions => { :class_name => 'AuditLogEntry', :entity_id => ale.id }) 

    if ale.user_id.nil? 
     u = User.first 
    else 
     u = User.first :conditions => ['id != ?', ale.user_id] 
    end 
    ale.user_id = u.id 
    assert !ale.save 

    assert !ale.destroy 
    end 
end 
1
उपयोगकर्ता गतिविधि (CRUD) नज़र रखने के लिए

, मैं बना लिया है एक वर्ग लॉगर से विरासत, और अब मैं पर नज़र रखने के उपयोगकर्ता के लिए एक से थोड़ा प्लगइन लिखने के लिए रंदा रहा हूँ कि मैं किसी भी आरओआर आवेदन के लिए उपयोग कर सकते हैं। मैंने पहले से ही जांच की है कि ऐसा प्लगइन है लेकिन मैंने नहीं देखा। मुझे लगता है कि पेपर-ट्रेल जैसे कई मणि हैं, act_as_audited या itslog लेकिन मैं प्लगइन का उपयोग करना पसंद करता हूं। कोई सुझाव? http://robaldred.co.uk/2009/01/custom-log-files-for-your-ruby-on-rails-applications/comment-page-1/#comment-342

अच्छा कोडिंग