0

I've got an Activerecord Model called a filter, Filters can apply to multiple objects via polymorphic relationships that I have dubbed 'filterabe'

I have another object called an AssignmentRule, which in this case is largely a collection of filters.

the assignment rule has an after_create and looks something like this:

class AssignmentRule < ApplicationRecord
  has_many :filters, as: :filterable, dependent: :destroy
  after_create :add_scope_filters
        
  def add_scope_filters
    if initial_scope_type
      if initial_scope_type == 'staff'
        filter = Filter.new
        filter.filter_type = 'all_bosses'
        filter.user_id = creator_id
        filter.course_id = self.course_id
        filter.value = '["'+creator_id.to_s+'"]'
        filter.view_type = 'AssignmentRule'
        filter.locked = true
        self.filters << filter
        initial_scope_type = nil
        save
      else

      end
      #update_attribute(:initial_scope_type, nil)
    end
  end

end

because assignment rules frequently get duped, I don't want this rule to fire for dupes, only for originals. So originals will be created with an initial_scope_type with a string value. After the rule fires I don't want to string value to remain, so I set it to nil and save.

The problem is that it's not saving???

I put a debugger on the call to save and I had this terminal interaction:

>initial_scope_type = nil
nil
>initial_scope_type
nil
>save
  SQL (1.1ms)  UPDATE `assignment_rules` SET `id` = 144, `course_id` = 195, `creator_id` = 18279, `created_at` = '2020-07-24 11:00:24', `updated_at` = '2020-07-24 11:00:24', `edits_assignment_rule_id` = 128, `editor_id` = 18279, `initial_scope_type` = 'staff' WHERE `assignment_rules`.`id` = 144
true
>wtf
undefined local variable or method `wtf' for #<AssignmentRule:0x00007f9b3b55a608>

Things I've tried:

Calling update_attribute instead (see comment in code), adding self. to my initial_scope_type like this: self.initial_scope_type = nil

the behavior remains the same.... I'm so confused, this is a simple assignment, why doesn't it work?

Thanks in advance for any answers!

I'm using ruby 2.6.5 on rails 5.0.7.2 with mysql 8.0.18

Update:

calling initial_scope_type with self seems to have slightly different consequences but the result is the same:

>self.initial_scope_type
"staff"
>self.initial_scope_type = nil
nil
>self.initial_scope_type
nil
>self
#<AssignmentRule id: 149, course_id: 195, creator_id: 18279, created_at: "2020-07-24 17:06:02", updated_at: "2020-07-24 17:06:02", edits_assignment_rule_id: 148, editor_id: 18279, initial_scope_type: nil>
>self.save
  SQL (2.5ms)  UPDATE `assignment_rules` SET `id` = 149, `course_id` = 195, `creator_id` = 18279, `created_at` = '2020-07-24 13:06:02', `updated_at` = '2020-07-24 13:06:02', `edits_assignment_rule_id` = 148, `editor_id` = 18279 WHERE `assignment_rules`.`id` = 149
true

when self is called the sql is slightly different on save, instead of deliberately setting initial_scope_type to staff like in the above example, its omitted all together. Am I missing something do I need to make a special call to set it to null?

Additional update: This time I bookended my debugging with database calls.

>AssignmentRule.find(self.id)
  AssignmentRule Load (0.8ms)  SELECT  `assignment_rules`.* FROM `assignment_rules` WHERE `assignment_rules`.`id` = 151 LIMIT 1
#<AssignmentRule id: 151, course_id: 195, creator_id: 18279, created_at: "2020-07-24 17:43:54", updated_at: "2020-07-24 17:43:54", edits_assignment_rule_id: 150, editor_id: 18279, initial_scope_type: "staff">
>self.initial_scope_type
"staff"
>self.initial_scope_type = nil
nil
>self.initial_scope_type
nil
>self
#<AssignmentRule id: 151, course_id: 195, creator_id: 18279, created_at: "2020-07-24 17:43:54", updated_at: "2020-07-24 17:43:54", edits_assignment_rule_id: 150, editor_id: 18279, initial_scope_type: nil>
>self.save
  SQL (0.9ms)  UPDATE `assignment_rules` SET `id` = 151, `course_id` = 195, `creator_id` = 18279, `created_at` = '2020-07-24 13:43:54', `updated_at` = '2020-07-24 13:43:54', `edits_assignment_rule_id` = 150, `editor_id` = 18279 WHERE `assignment_rules`.`id` = 151
true
>AssignmentRule.find(self.id)
  AssignmentRule Load (0.7ms)  SELECT  `assignment_rules`.* FROM `assignment_rules` WHERE `assignment_rules`.`id` = 151 LIMIT 1
#<AssignmentRule id: 151, course_id: 195, creator_id: 18279, created_at: "2020-07-24 17:43:54", updated_at: "2020-07-24 17:43:54", edits_assignment_rule_id: 150, editor_id: 18279, initial_scope_type: "staff">
acolchagoff
  • 1,926
  • 3
  • 18
  • 30
  • 1
    Answered here https://stackoverflow.com/questions/5183664/why-isnt-self-always-needed-in-ruby-rails-activerecord – Deepak Jul 24 '20 at 15:51
  • @Deepak It's a good guess, but I don't think thats my problem. I don't have any methods that are clobbering the default setter method. I also did a codebase wide search for `def initial_scope_type` just to be sure. Also earlier in the code initial_scope_type returned 'staff' which is the database value. so it appears to be resolving correctly when read. – acolchagoff Jul 24 '20 at 16:01
  • 1
    It is not a guess, when you call a getter method the ruby will check in current class and ancestor class if the getter method or variable is defined. If it finds it will return the value that is how you're getting the correct value for title i.e 'staff'. But, when you're assigning nil to title you're actually creating new local variable called 'title'. You need to use self.title to update value of title attribute of AssignmentRule object. So ruby knows where to check the title setter method and update the value. – Deepak Jul 24 '20 at 16:21
  • @Deepak I've posted an update above that shows what happens when I use self, the call to the database is slightly different, but the symptoms are the same, it still won't set the database value to NULL – acolchagoff Jul 24 '20 at 16:27
  • 1
    I don't understand. It works for me I have tried with different example but same behaviour trying to update attribute in after create. Checkout the screenshot: https://1drv.ms/u/s!Aqp64KDCpt33h7BgoSyByOz8T4t-Xw?e=RQDlcW. Also, check the self object after you assign value to initial_scope_type using self. – Deepak Jul 24 '20 at 16:44
  • @Deepak, Thanks for your efforts, I know, it's really weird. I've updated my update in the question above with a call to self before calling self.save, I hope that helps. – acolchagoff Jul 24 '20 at 17:13
  • 1
    I see the object as already updated with nil (initial_scope_type: nil). I think, since it is in same transaction the nil value is already updated to initial_scope_type and save is not have any affect. Please check in database if the value is updated to nil and if it is updated the save method call is not required in after_create. – Deepak Jul 24 '20 at 17:24
  • I've added an additional update with database calls. – acolchagoff Jul 24 '20 at 17:56
  • 1
    This is weird, I will have to install the same rails version and check. I am not sure @denodster. – Deepak Jul 24 '20 at 18:06
  • it appears that updating to rails 5.1 sorts this out – acolchagoff Jul 24 '20 at 20:28

1 Answers1

0

This is a bug in Rails 5.0. I updated to Rails 5.1 and everything started acting as expected.

acolchagoff
  • 1,926
  • 3
  • 18
  • 30