Accessing model attributes in ActiveSupport::Concern module

63 views
Skip to first unread message

Felix Gläske

unread,
Sep 18, 2013, 1:11:59 PM9/18/13
to rubyonra...@googlegroups.com
I have some models which share the same functionality just on other paths. So I decided to put these methods in a module and set the path in the model. My problem is that I'm not able to access the attribute in my module.

my model:
class Job < ActiveRecord::Base
  include ImageModel

  image_dir = "jobs"
end
my module:
module ImageModel
  extend ActiveSupport::Concern

  def delete_image
      unless pic_link == "" || pic_link == nil
        begin
          if File.delete(Rails.root.join("public", "images", image_dir, pic_link))
            return true
          else
            return false
          end
        rescue
          return true #an error occured but when the image does not exist we still return true
        end
      end

      return true
    end

    def replace_image(new_image)
      File.open(Rails.root.join("public", "images", image_dir, new_image.original_filename), "wb") do |f|
        if f.write new_image.read
          delete_image
          pic_link = new_image.original_filename
          return true #everything went fine
        else
          return false #return false if new image could not be written
        end
      end
    end
end
The error I get:
undefined local variable or method `image_dir' for #<Job:0x007f8a93b9e8d8>
on this line:
File.open(Rails.root.join("public", "images", image_dir, new_image.original_filename), "wb") do |f|

Did I miss something or did I oversee something important?

Felix

Josh Jordan

unread,
Sep 20, 2013, 11:39:22 AM9/20/13
to rubyonra...@googlegroups.com
Felix,

You defined image_dir as a local variable in the scope of the Job class. It goes out of scope (and, since nothing else references it, gets cleaned up) after the class definition of Job is evaluated. Instead, define image_dir on instances of Job:

class Job < ActiveRecord::Base
  include ImageModel

  def image_dir
    @image_dir ||= 'jobs'
  end
end

Better yet, since image_dir is the same for every instance of Job, make it a class method:

class Job < ActiveRecord::Base
  include ImageModel

  def self.image_dir
    @image_dir ||= 'jobs'
  end
end

and access it through the model's class:

File.open(Rails.root.join('public', 'images', self.class.image_dir, new_image.original_filename), 'wb') do |f|

Jordon Bedwell

unread,
Sep 20, 2013, 5:53:20 PM9/20/13
to rubyonra...@googlegroups.com
On Fri, Sep 20, 2013 at 6:39 AM, Josh Jordan <josh....@gmail.com> wrote:
> Felix,
>
> You defined image_dir as a local variable in the scope of the Job class. It
> goes out of scope (and, since nothing else references it, gets cleaned up)
> after the class definition of Job is evaluated. Instead, define image_dir on
> instances of Job:
>
> class Job < ActiveRecord::Base
> include ImageModel
>
> def image_dir
> @image_dir ||= 'jobs'
> end
> end
>
> Better yet, since image_dir is the same for every instance of Job, make it a
> class method:
>
> class Job < ActiveRecord::Base
> include ImageModel
>
> def self.image_dir
> @image_dir ||= 'jobs'
> end
> end
>
> and access it through the model's class:
>
> File.open(Rails.root.join('public', 'images', self.class.image_dir,
> new_image.original_filename), 'wb') do |f|

To add a note, if image_dir is persistently stored in the db you can
use the default opt in your Migration.
Reply all
Reply to author
Forward
0 new messages