Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Already on GitHub? Sign in to your account

after_create can't access habtm relationships in private methods #5934

Closed
meliho opened this Issue Apr 23, 2012 · 7 comments

Comments

Projects
None yet
5 participants

meliho commented Apr 23, 2012

I have 3 model objects - User, Feed, Post.

User <- habtm -> Feed
Post belongs to Feed

When a post is created, I iterate through all of the users off of the feed, and attach them to that user through an after_create callback. When I moved the callback method to be private, I was no longer able to access the users through the feed association. Once I moved it back to being public, I was able to access the associations again.

It should either be noted somewhere in documentation that associations are restricted to public methods, or association scoping should be possible

I am in Ruby 3.0.10

Member

sikachu commented Apr 23, 2012

Heh, that shouldn't happen. Can i see (some of) your model code?

meliho commented Apr 23, 2012

Of course:

class User < ActiveRecord::Base
has_and_belongs_to_many :feeds

has_many :post_users
has_many :posts, :through => :post_users
end

class Feed < ActiveRecord::Base
has_many :posts

has_and_belongs_to_many :users

validates_uniqueness_of :url
end

class Post < ActiveRecord::Base
belongs_to :feed

has_many :post_users
has_many :users, :through => :post_users

after_create :attach_to_users

def self.get_new_posts(feed_url, feed_id, last_update_date = nil)
options = last_update_date.nil? ? {} : {:if_modified_since => last_update_date}
feed = Feedzirra::Feed.fetch_and_parse(feed_url, options)

if not feed.nil? and not feed.is_a? Fixnum then 
  add_entries(feed.entries, feed_id)
end

end

private

def attach_to_users
feed = Feed.find_by_id(self.feed_id)
feed.users.each do |user|
begin
PostUser.create!(
:post_id => self.id,
:user_id => user.id,
:read_state => 1
)
puts "created"
rescue ActiveRecord::StatementInvalid => e
raise e unless /Mysql2::Error: Duplicate entry/.match(e)
end
end
end

def self.add_entries(entries, feed_id)
entries.each do |entry|
begin
unless exists? :uid => entry.id
create!(
:title => entry.title.html_safe,
:content => entry.content.nil? ? entry.summary.html_safe : entry.content.html_safe,
:url => entry.url,
:published_at => entry.published,
:uid => entry.id,
:feed_id => feed_id
)
end
rescue
next
end
end
end
end

Aupajo commented Apr 23, 2012

Just passing through, fixed up code paste:

class User < ActiveRecord::Base
  has_and_belongs_to_many :feeds

  has_many :post_users
  has_many :posts, :through => :post_users
end

class Feed < ActiveRecord::Base
  has_many :posts

  has_and_belongs_to_many :users

  validates_uniqueness_of :url
end

class Post < ActiveRecord::Base
  belongs_to :feed

  has_many :post_users
  has_many :users, :through => :post_users

  after_create :attach_to_users

  def self.get_new_posts(feed_url, feed_id, last_update_date = nil)
    options = last_update_date.nil? ? {} : {:if_modified_since => last_update_date}
    feed = Feedzirra::Feed.fetch_and_parse(feed_url, options)

    if not feed.nil? and not feed.is_a? Fixnum then 
      add_entries(feed.entries, feed_id)
    end
  end

  private

  def attach_to_users
    feed = Feed.find_by_id(self.feed_id)
    feed.users.each do |user|
      begin
        PostUser.create!(
          :post_id => self.id,
          :user_id => user.id,
          :read_state => 1
        )
        puts "created"
      rescue ActiveRecord::StatementInvalid => e
        raise e unless /Mysql2::Error: Duplicate entry/.match(e)
      end
    end
  end

  def self.add_entries(entries, feed_id)
    entries.each do |entry|
      begin
        unless exists? :uid => entry.id
          create!(
            :title => entry.title.html_safe,
            :content => entry.content.nil? ? entry.summary.html_safe : entry.content.html_safe,
            :url => entry.url,
            :published_at => entry.published,
            :uid => entry.id,
            :feed_id => feed_id
          )
        end
      rescue
        next
      end
    end
  end
end

I created an application under Rails 3.0.10 and then created a Post with a Feed that had many users. All users associated with the Feed were successfully linked to the Post using the code as is. I did this under sqlite and mysql (in case its some adapter issue), both worked fine. Are you still having this problem @monvural ? Maybe some stack trace?

meliho commented May 10, 2012

Sorry for the slow response.

Will checkout the version that was broken, and try to step through the
code and get a stack trace. Will get this this weekend.

Melih Onvural
http://www.onvural.net/melih

On Thu, Apr 26, 2012 at 12:40 AM, Gary Greyling
reply@reply.github.com
wrote:

I created an application under Rails 3.0.10 and then created a Post with a Feed that had many users. All users associated with the Feed were successfully linked to the Post using the code as is. I did this under sqlite and mysql (in case its some adapter issue), both worked fine. Are you still having this problem? Maybe some stack trace?


Reply to this email directly or view it on GitHub:
#5934 (comment)

Member

senny commented Oct 6, 2012

@monvural any progress on this one?

@steveklabnik can you tag this with needs feedback?

meliho commented Nov 5, 2012

I could repro it every time no matter what my server configuration was when I filed the bug. When I go back to that place in my GIT repo (which I saved so that I could reference the code at that point for this bug report), I can't reproduce the error.

I'm wondering if there was a thread running that I thought I had started and stopped, but that wasn't properly recycling itself. Have since re-worked how delayed_jobs works on our staging server which could be the solution to all of this.

I think at this point, we should close as can't repro.

@meliho meliho closed this Nov 5, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment