@@ -752,10 +752,11 @@ def author
752752 before_validation :set_data_dir , :set_firecloud_workspace_name , on : :create
753753 after_validation :assign_accession , on : :create
754754 # before_save :verify_default_options
755- after_create :make_data_dir , :set_default_participant , :check_bucket_read_access
755+ after_create :make_data_dir , :set_default_participant , :check_bucket_read_access , :log_study_creation
756756 before_destroy :ensure_cascade_on_associations
757757 after_destroy :remove_data_dir
758758 before_save :set_readonly_access
759+ after_update :log_study_state
759760
760761 # search definitions
761762 index ( { "name" => "text" , "description" => "text" } , { background : true } )
@@ -1836,12 +1837,61 @@ def delete_convention_data
18361837 end
18371838 end
18381839
1840+ ## State tracking methods
1841+
18391842 def last_public_date
1840- history_tracks . where ( 'modified.public' : true ) . order_by ( created_at : :desc ) . first &.created_at
1843+ history_tracks . where ( 'modified.public' : true ) . order_by ( created_at : :desc ) . last &.created_at
18411844 end
18421845
18431846 def last_initialized_date
1844- history_tracks . where ( 'modified.initialized' : true ) . order_by ( created_at : :desc ) . first &.created_at
1847+ history_tracks . where ( 'modified.initialized' : true ) . order_by ( created_at : :desc ) . last &.created_at
1848+ end
1849+
1850+ # find the last time an attribute changed in the history
1851+ def last_change_for ( field )
1852+ history_tracks . select { |h | h . modified . keys . include? ( field . to_s ) } . last
1853+ end
1854+
1855+ # determine if a field changed from a given value
1856+ def field_changed_from? ( history_track , field , value )
1857+ return false if history_track . nil?
1858+
1859+ history_track . original [ field ] == value && history_track . modified [ field ] != value
1860+ end
1861+
1862+ # helper to determine if a study was just made public
1863+ def was_just_published? ( cutoff : nil )
1864+ track = last_change_for ( :public )
1865+ field_changed_from? ( track , :public , false ) && track . created_at >= ( cutoff || 1 . second . ago )
1866+ end
1867+
1868+ # helper to determine if a study was just initialized
1869+ def was_just_initialized? ( cutoff : nil )
1870+ track = last_change_for ( :initialized )
1871+ field_changed_from? ( track , :initialized , false ) && track . created_at >= ( cutoff || 1 . second . ago )
1872+ end
1873+
1874+ # basic Mixpanel props for study state tracking
1875+ def mixpanel_state_props
1876+ {
1877+ studyAccession : accession ,
1878+ created_at :,
1879+ domain : user . email . split ( '@' ) . last ,
1880+ numCells : cell_count ,
1881+ public :,
1882+ last_public_date :,
1883+ initialized :,
1884+ last_initialized_date :
1885+ }
1886+ end
1887+
1888+ def log_study_creation
1889+ MetricsService . log ( 'study-creation' , mixpanel_state_props , user )
1890+ end
1891+
1892+ # only log state when a study is published/initialized
1893+ def log_study_state
1894+ MetricsService . log ( 'study-state' , mixpanel_state_props , user ) if was_just_published? || was_just_initialized?
18451895 end
18461896
18471897 private
0 commit comments