using includes in rails models

Hi,

I'm trying to use the amatch gem (http://flori.github.com/amatch/) to
help with some validations. In the documentation examples
(http://flori.github.com/amatch/doc/index.html
), after the require 'amatch', there's an include Amatch.

Where would I put this include? I tried putting it at the very top of my
model file, but when I opened up the rails console, and tested it out
using:

m = Sellers.new("hello")

I get this output:

NameError: uninitialized constant Sellers
  from
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:443:in
`load_missing_constant'
  from
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:80:in
`const_missing'
  from
/Library/Ruby/Gems/1.8/gems/activesupport-2.3.5/lib/active_support/dependencies.rb:92:in
`const_missing'
  from (irb):1

I put the gem in my environment.rb file as well. Any help is
appreciated!

'include' statements usually go inside a class -- essentially,
'include Amatch' adjusts the class you're defining by adding the
methods from the Amatch module.

A 'require' statement, on the other hand, just tells Ruby to bring in
the contents of the filename you specify.

So you probably want this kind of thing:

require 'amatch'
class Seller
  include Amatch
  # Rest of your class definition here
end

Try that and see if it resolves the error. If not, there may be a
problem finding the amatch file itself.

Chris

Try

Chris,

Thank you for the reply. putting the include under the model class,
which worked! Thanks very much for that.

In my script/console, I tried instantiating a new "Sellers" object
(Sellers is one of the types of edit distance methods), with this code:

m = Sellers.new("hello")

but still got the same error output.

however, I created a new object of my model, Responses:

x = Responses.new

after which I was able to create an amatch Sellers object within a
function:

def title_must_have_changed_by_one_letter
    m = Sellers.new(first_response)
    errors.add_to_base("Sorry, the last submitted response must have
changed by one letter") if m.match(second_response) != 1.0
end

That makes sense to me. I'm just curious why I wasn't able to make a new
Sellers object in the first page?

Thanks again for your help!

Chris Mear wrote:

Did you restart or reload your console after making the change to
seller.rb? Sometimes there are changes that the console doesn't pick
up until you reload it.

Chris

Hi Chris,

Oh, I don't have a Seller model. The Seller object I was trying to
instantiate was an amatch class inside of my Response model. Sorry for
the confusion.

I guess what I'm trying to say is: is there any way to instantiate the
amatch Seller class in the console, after you have create a new Response
object (which is the model - response.rb)?

Also, I tried accessing my views in my browser and got this error:

NameError in Games#show

Showing app/views/games/show.html.erb where line #8 raised:

uninitialized constant Response::Amatch
Extracted source (around line #8):

5: </p>
6: <h2>Responses</h2>
7:
8: <% @game.responses.each do |r| %>
9: <p>
10: <b><%=h r.title %></b><br />
11: <%= time_ago_in_words(r.created_at) %> ago

Any thoughts on what could be the problem? I tried adding the include
Amatch in my Game model as well, but got this error:

NameError in GamesController#show

uninitialized constant Game::Amatch

Thanks again!

Chris Mear wrote:

In your console, you either need to

include Amatch

m = Sellers.new(“hello”)

or

m = Amatch::Sellers.new(“hello”)

Phillip Ridlen

@philtr

Philip,

Thank you for your help, that worked! I put that extra code in the
model, but I still get the uninitialized constant error in my browser
when accessing the show action. Not sure what may be the issue.

Thanks again for your help!

Phillip Ridlen wrote:

If I’m understanding you correctly, you want to load up script/console (or rails console), instantiate a Seller object, and then access it from the browser? I’m not sure you can do that, because your console is a separate instance of the application (it may access the same database but it’s running in a different location in memory if I understand it correctly).

If you’re just trying to get it to work in your application (no console), then where are you putting require 'amatch'? Somewhere all of the parts of your app need it, I hope!

Phillip Ridlen

@philtr

Hi Philip,

Sorry, I was actually asking two different questions in my last reply.
You've answered my question about the console, thanks for your help!
It's much clearer now.

I've put the " include 'amatch' " in both my Post model and my Response
model, which have a one to many relationship. However, I get this error
message:

NameError in Posts#show

Showing app/views/posts/show.html.erb where line #8 raised:

uninitialized constant Response::Amatch

here's my code for the post model:

class Post < ActiveRecord::Base
  include Amatch
  has_many :responses
  validates_presence_of :title
  validates_length_of :title, :within => 3..10
end

and the Response model:

class Response < ActiveRecord::Base
  include Amatch
  belongs_to :post
  validates_uniqueness_of :title
  validates_presence_of :title
  validates_length_of :title, :within => 3..5
  validate :title_must_have_changed_by_one_letter

protected

  def title_must_have_changed_by_one_letter
    m = Amatch::Sellers.new(title)
    errors.add_to_base("Sorry, you must change the last submitted string
by one letter") if m.match(self.response.last) != 1.0
  end
end

Would I need to include Amatch in the controller and views as well?

Phillip Ridlen wrote:

I believe you’ve included it in the correct place, but where is your require 'amatch'?

Hi Philip,

I put the amatch gem in the environment.rb file as config.gem 'amatch'

I tried the require 'amatch' in line 1 in each of my models and got this
error:

MissingSourceFile in PostsController#show

no such file to load -- amatch

Thank you!

Phillip Ridlen wrote:

I’m unable to duplicate your problem with Rails 2.3.5.

I just learned that config.gem "amatch" automatically requires the library with the same name, so you shouldn’t need to put require "amatch" anywhere in the application. Same goes for Rails 3 and Bundler.

I just whipped up a simple scaffold application, here’s what it looks like (Maybe this will help(?)–I’m not very familiar with how Amatch works, maybe I’ll look into that):

config/environment.rb

config.gem “amatch”

app/models/post.rb

class Post < ActiveRecord::Base

include Amatch

end

app/controllers/posts_controller.rb

class PostsController < ApplicationController

def index

@posts = Post.all

m = Post::Sellers.new(“hello”)

respond_to do |format|

format.html # index.html.erb

format.xml { render :xml => @posts }

end

end

end

This doesn’t throw any errors for me.

Phillip Ridlen

@philtr

Thanks Philip. After reading your response, I tried doing another dummy
application myself, and in the middle of getting everything set up, I
realized that I didn't restart the script/server after adding the
include. So I went back to my other application, and this worked.
Occam's razor :-).

Sorry to hound you with additional questions, but I was wondering if you
had time for one more.

I'm having a hard time limiting the scope of new comments to the Post
model. So, for validates_uniqueness_of :title in the comment.rb model,
that uniqueness would only be attached to the post I'm commenting to,
not globally among all comments in the application.

I tried putting this in comment.rb:

validates_uniqueness_of :title, :scope => :post

but got this error message in my terminal:

Processing CommentsController#create (for 127.0.0.1 at 2010-08-16
21:28:32) [POST]
  Parameters: {"comment"=>{"title"=>"rent"}, "commit"=>"Submit Your
Comment",
"authenticity_token"=>"z5AzsFgaJPdvGiTyy3Yeyb8f0RV+dmpdw5PanAadjOw=",
"game_id"=>"5"}
  Post Load (0.2ms) SELECT * FROM "posts" WHERE ("posts"."id" = 5)
  CACHE (0.0ms) SELECT * FROM "posts" WHERE ("posts"."id" = 5)
  Response Load (0.0ms) SQLite3::SQLException: no such column:
comments.posts: SELECT "comments".id FROM "comments" WHERE
("comments"."title" = 'rent' AND "comments".post = 5) LIMIT 1

ActiveRecord::StatementInvalid (SQLite3::SQLException: no such column:
comments.post: SELECT "comments".id FROM "comments" WHERE
("comments"."title" = 'rent' AND "comments".post = 5) LIMIT 1):
  app/controllers/comments_controller.rb:4:in `create'

Rendered rescues/_trace (110.5ms)
Rendered rescues/_request_and_response (1.2ms)
Rendering rescues/layout (internal_server_error)

Thank you!

Phillip Ridlen wrote: