0

I have a very simple model using Mongoid. I've added the use of Redcarpet to parse the MD and store it. However during update_attributes it is throwing an exception. Running the model and running the update through rails c works fine.

class Post
  include Mongoid::Document
  field :contents_markdown
  field :contents

  key :title

  before_create :markdown
  before_save :markdown

  protected
  def markdown
    if self.contents_markdown
      self.contents = Redcarpet.new(self.contents_markdown).to_html.html_safe
    end
  end
end

Here is the controller that blows up.

def update
  @post = Post.find(params[:id])

  respond_to do |format|
    if @post.update_attributes(params[:post])
      format.html { redirect_to @post, notice: 'Post was successfully updated.' }
      format.json { head :ok }
    else
      format.html { render action: "edit" }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end

Here is the exception and stacktrace. The line numbers will be slightly off as I have removed stuff from the model.

uninitialized constant Post::Redcarpet

app/models/post.rb:20:in `markdown'
app/controllers/posts_controller.rb:62:in `block in update'
app/controllers/posts_controller.rb:61:in `update'

If it matters, I'm running MRI 1.9.2-p290 and Rails 3.1-rc5.

Edit - This all works fine when running tests and running through the console. However going through the controller to update/create the model seems to always fail. Additionally from the stacktrace, you can see the model is in the standard location.

tgandrews
  • 12,349
  • 15
  • 43
  • 55

2 Answers2

1

You can try changing Redcarpet.newto ::Redcarpet.new which will tell Ruby to look for a top-level constant Redcarpet. I think that will likely fix it, but it's possible that the problem is something more complex.

Emily
  • 17,813
  • 3
  • 43
  • 47
  • Ruby will search through the parent namespaces, but the error is generally reported in the originating namespace. Using `::Redcarpet` is useful when there's a conflicting declaration, but in this case there's no definition at all and the auto-loader isn't grabbing it. – tadman Aug 16 '11 at 21:13
  • I got the following exception when I changed it. `uninitialized constant Redcarpet` – tgandrews Aug 16 '11 at 21:15
  • 1
    I've gotten similar errors in models and had them fixed by doing this. I think there's sometimes some weirdness when using autoload, which is used heavily in Rails. I haven't looked into the details of why it fixes it, but it sometimes does. – Emily Aug 16 '11 at 21:17
  • When testing this in the console, are you in a fresh console session, or one in which you've already tried some other things out? Try quitting and restarting the console, and see if you get the same error. – Emily Aug 16 '11 at 21:19
  • Yeah, I've tried closing and reopening it. Rspec tests using the model are all fine as well. – tgandrews Aug 16 '11 at 21:23
1

You might be missing a require or a gem declaration depending on how you're using Redcarpet.

The Rails auto-loader will generally catch these if that is defined in a standard location like app/models or, as is optional, lib/.

Usually you can fix this by putting the appropriate require statement in a config/initializers/redcarpet.rb type file, or altering your Gemspec as necessary.

tadman
  • 208,517
  • 23
  • 234
  • 262
  • I have the gem dependency in my Gemfile. The model works when running through the `rails c`. – tgandrews Aug 16 '11 at 21:14
  • I've noticed that sometimes declaring the `gem` is necessary to make the `require` load from the correct path, but the `require` still has to be done. Maybe the console environment has a different `$LOAD_PATH` or autoloader settings. – tadman Aug 16 '11 at 21:15
  • Thanks. I've added a require in the initializers and this fixed it. I'll accept your answer as soon as I can. – tgandrews Aug 16 '11 at 21:22