Anri
Anri

Reputation: 6265

Method variables in rails models

When I write ActiveRecord models in rails I want to make sure that local variables I use in my method will remain local to the scope of the method I write, and I will not be accidentally overwriting model property in future.

For example:

class User < ActiveRecord::Base
  after_save :do_something

  def do_something
    # ... some logic
    group = "some value"
    # ... more logic 
  end    
end

How do I make sure that if I happen to add group property to my model in future - my method will not accidentally overwrite it?

I thought about class variables, but it's not what they are for, and I think using them will be a bad practice.

Upvotes: 1

Views: 3733

Answers (2)

MikaAK
MikaAK

Reputation: 2364

In ruby you can define local variables and instance variables with the same name.

class Example
  @instance = 4

  def example_method
    @instance += 1
  end

  def example_2
    instance = 0
    10.times { instance += 1 }
  end
end

e = Example.new

e.example_2 # => 10
e.instance # => 4
e.example_method # => 5
e.instance # => 5

these will not conflict

example_2

is returning the local variable which is then destroyed if not used

example_method

is setting the instance variable which will save per instance of the class or in this case for active record will save to database.

Also note you can be more explicit when referring to instance variables and say

self.instance

EDIT

your group variable inside your do_something is a local variable and will not cause conflict with @group which is a instance variable of a higher scope

EDIT2

I have a projects model in my application

class Project < ActiveRecord::Base
  VALID_NAME_REGEX = /(\A[\w ]+)/
  VALID_URL_REGEX = URI::regexp(["http", "https"])

  validates :name, :presence => true,
                 :uniqueness => true,
               :length => {
                  :maximum => 24
               },
           :format => {
             :with => VALID_NAME_REGEX,
             :message => "Only allow numbers letters hyphens and underscores"
         }

  after_save :test
  def test
    name = 'bob'
  end
end

after setting my model to this and creating a new instance of it on my website I can confirm this will not set my projects name to bob

Upvotes: 1

thegravian
thegravian

Reputation: 448

Using a local variable, that is a variable not prefixed by @ or @@ will not cause a namespace collision with future model attributes. Those attributes would have to be referenced in such a way similar to self.group. You could run into trouble if your code in your model tweaks the class by adding fields or members to the object at runtime, or if you mess with the class definition, but just declaring a local variable in a method will not collide with an instance variable that corresponds to an ORM field.

Additionally, if you've got methods to mutate fields in your model and you try to access them by saying

def getgroup
  group
end

this won't work, either. group in this context is undefined, because it doesn't refer to anything else in the local scope

Upvotes: 1

Related Questions