Ruby on Rails + MongoDB and MongoID - ruby-on-rails-3

I have created a sample DB with MongoDB with data from a JSON file on mongodbs website
I have imported it with the following command.
mongoimport --db test --collection zips --file zips.json
The data is being processed and when I try to search for data in the console it will show up, so far so good.
My problem is when I'm trying to use the DB with my Rails app. I have created a Class, City, the code looks like this.
class City
include Mongoid::Document
field :c, as: :city, type: String
field :l, as: :loc, type: Array
field :p, as: :population, type: Integer
field :s, as: :state, type: String
field :_id, type: Integer
end
And my mongoid.yml file looks like this
development:
# Configure available database sessions. (required)
sessions:
# Defines the default session. (required)
default:
# Defines the name of the default database that Mongoid can connect to.
# (required).
database: exjobb
# Provides the hosts the default session can connect to. Must be an array
# of host:port pairs. (required)
hosts:
- localhost:27017
options:
options:
test:
sessions:
default:
database: exjobb
hosts:
- localhost:27017
options:
consistency: :strong
# In the test environment we lower the retries and retry interval to
# low amounts for fast failures.
max_retries: 1
retry_interval: 0
Activerecord is disabled. When Im starting rails console and try City.where...
I get the following output.
City.where(city: "Acmar")
=> #<Mongoid::Criteria
selector: {"c"=>"Acmar"}
options: {}
class: City
embedded: false>
And if I try City.first an error is thrown
NoMethodError: undefined method `to_sym' for nil:NilClass
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/sessions.rb:409:in `__evaluate__'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/sessions.rb:357:in `__database_name__'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/sessions.rb:198:in `database_name'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/sessions.rb:429:in `current_database_name'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/sessions.rb:228:in `mongo_session'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/sessions.rb:171:in `collection'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/contextual/mongo.rb:256:in `initialize'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/contextual.rb:48:in `new'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/contextual.rb:48:in `create_context'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/contextual.rb:31:in `context'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/contextual.rb:21:in `rescue in first'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/contextual.rb:19:in `first'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/mongoid-3.1.2/lib/mongoid/finders.rb:117:in `first'
from (irb):1
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/railties-3.2.11/lib/rails/commands/console.rb:47:in `start'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/railties-3.2.11/lib/rails/commands/console.rb:8:in `start'
from /Users/admin/.rvm/gems/ruby-1.9.3-p374/gems/railties- 3.2.11/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
I've uploaded my code here, please clone and try to help me, im stuck.
As you can see, my db is not empty. http://i.stack.imgur.com/Bho2H.png

Mongoid (using similar mapping conventions to ActiveRecord) pluralizes the class name to get the collection name. It looks like you have a collection called city but Mongoid will have mapped your class to a collection called cities.
You can override the collection name:
class City
store_in collection: "city"
end
or better still import your data into a cities collection.

Related

ThinkingSphinx Error: such filter attribute

I am trying to integrate ThinkingSphinx into my project using the doc. For a User model with attributes first_name and last_name I have created the indexes as:
User.rb
define_index do
indexes :first_name
indexes :last_name
end
Then I run the commands:
rake ts:index
rake ts:start
This starts my search. I get the results when I use the following command to search:
User.search('swati')
But When I run
User.search :with => {:first_name => "swati"}
It gives me the error:
Sphinx Sphinx Daemon returned error: index user_core: no such filter attribute 'first_name'
Sphinx Caught Sphinx exception: index user_core: no such filter attribute 'first_name' (0 tries left)
ThinkingSphinx::SphinxError: index user_core: no such filter attribute 'first_name'
from /home/swati/.rvm/gems/ruby-1.9.3-p286/gems/thinking-sphinx-2.0.13/lib/thinking_sphinx/search.rb:438:in `block in populate'
from /home/swati/.rvm/gems/ruby-1.9.3-p286/gems/thinking-sphinx-2.0.13/lib/thinking_sphinx/search.rb:606:in `call'
from /home/swati/.rvm/gems/ruby-1.9.3-p286/gems/thinking-sphinx-2.0.13/lib/thinking_sphinx/search.rb:606:in `retry_on_stale_index'
from /home/swati/.rvm/gems/ruby-1.9.3-p286/gems/thinking-sphinx-2.0.13/lib/thinking_sphinx/search.rb:426:in `populate'
from /home/swati/.rvm/gems/ruby-1.9.3-p286/gems/thinking-sphinx-2.0.13/lib/thinking_sphinx/search.rb:187:in `method_missing'
from /home/swati/.rvm/gems/ruby-1.9.3-p286/gems/railties-3.2.8/lib/rails/commands/console.rb:47:in `start'
from /home/swati/.rvm/gems/ruby-1.9.3-p286/gems/railties-3.2.8/lib/rails/commands/console.rb:8:in `start'
from /home/swati/.rvm/gems/ruby-1.9.3-p286/gems/railties-3.2.8/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
I searched for a possible solution on stackoverflow and it has been asked to run the commands rake ts:index and rake ts:rebuild. I have run this commands but it didn't help me.
Please help me figure out a solution for this.
Many thanks.
You should create an attribute with has in the index, rebuild, and then use with
has :first_name
Has creates an attribute, and with is used as a filter (for attributes) http://pat.github.com/ts/en/searching.html#filters
Also check http://pat.github.com/ts/en/indexing.html#attributes for filters.
Be carefull, rake ts:reindex and rake ts:rebuild are different.
If you add a new index, you need to rebuild.
If you are paranoiac like me, try everything:
rake ts:rebuild
rake ts:reindex
rake ts:restart
If it still doesn't work, make sure your index is defined properly.

How to use #valid_attributes in a before block in rails 3 and rspec?

I'm trying different blogs with examples of Rails 3 and RSpec. Yes it's on Windows, so the answer isn't not using Windows. No choice in that. Moving on...
I am able to run the spec either with rspec spec or rake spec:models so that seems fine. However if I try to use a before block with attributes it fails on creating a Person class with those attributes. The other tests are just there to show spec can run.
Made a Person model then updated the spec
\myapp\spec\models\person_spec.rb
require 'spec_helper'
describe Person do
before(:each) do
#valid_attributes = {
:first_name => "Foo",
:last_name => "Bar"
}
end
it "should create a new instance given valid attributes" do
Person.create!(#valid_attributes)
end
it "can be instantiated" do
Person.new.should be_an_instance_of(Person)
end
it "can be saved successfully" do
Person.create.should be_persisted
end
#pending "add some examples to (or delete) #{__FILE__}"
end
Here's the output of rake spec:models command
C:\Users\laptop\Documents\Sites\myapp>rake spec:models
C:/Ruby193/bin/ruby.exe -S rspec ./spec/models/person_spec.rb
Person
←[31m should create a new instance given valid attributes (FAILED - 1)←[0m
←[32m can be instantiated←[0m
←[32m can be saved successfully←[0m
Failures:
1) Person should create a new instance given valid attributes
←[31mFailure/Error:←[0m ←[31mPerson.create!(#valid_attributes)←[0m
←[31mActiveRecord::UnknownAttributeError:←[0m
←[31munknown attribute: first_name←[0m
←[36m # ./spec/models/person_spec.rb:13:in `block (2 levels) in <top (required)>'←[0m
Finished in 0.074 seconds
←[31m3 examples, 1 failure←[0m
Failed examples:
←[31mrspec ./spec/models/person_spec.rb:12←[0m ←[36m# Person should create a new instance given valid attributes←[0m
rake aborted!
C:/Ruby193/bin/ruby.exe -S rspec ./spec/models/person_spec.rb failed
So two out of three passed just not the one with attributes.
Anything in particular that would need to be setup for a before block to run or how are attributes passed in a test with Rails 3?
Also is there a way to get rid of those ]31m and such printouts for each spec line?
Thanks
It would appear from the error that ActiveRecord can't find the attribute :first_name that you are passing as part of #valid_attributes. That is, the problem isn't with how you are using RSpec, but with the attributes you are expecting a valid model to contain.
Check that you have a :first_name field or attribute on the Person model - and verify the exact spelling (:first_name vs :firstname or some other variation)
I should update this with the answer.
The Person model did in fact contain first_name and last_name but as noted by two people above the error I was receiving pointed to ActiveRecord not finding it.
In Windows, running rake db:migrate two or three times eventually fixed it even though it wasn't missing in the model.
If you're stuck on Windows dev, this may be a good thing to know!
I finally was able to put Lubuntu on a VirtualBox on Windows 7 and it ran fine and since then I have proceeded with other examples from there.
Cheers

Could not find table 'users'

UPDATE 4
See solution below!
**Update 3 **
If anyone is actually still reading this (I appreciate it!) I've been struggling around my code today (yes still a noob and in chapter 11 of the ruby on rails tutorial).
I've supposedly reset back to my last commit:
$ cd rails_screencast/sample_app/
$ git reset --hard 2396c0d288d132ffc43c82d5cbbc736a5258eed2
HEAD is now at 2396c0d Micropost Validations
When I check the site on local host it actually shows a list of users and not an ERROR page but when I run the test suite (autotest with spork - I've reset those a few times too to be sure) I still get all errors such as these shown below. I'm very curious about the "Could not find table 'users'" as it is in EVERY error #
108) Users signin success should sign a user in and out
Failure/Error: user = Factory(:user)
ActiveRecord::StatementInvalid:
Could not find table 'users'
# ./spec/requests/users_spec.rb:56:in `block (4 levels) in <top (required)>'
Finished in 0.9872 seconds
108 examples, 108 failures
Time to keep on plugging and looking at all these errors, if anyone can offer any insight or hints or ideas what to check I would appreciate it! Or if you need additional information I can post that too (just be very specific to which files to see as I'm not totally fluent in the lingo as many are already)
Update 2:
It seems that my reset messed something up with the factory settings as sometimes all my errors are pointing to line 5 of my micropost_spec.rb file specifically # the #user = Factory(:user) line... almost like my factories file isn't linked to anything any more. I am wondering if a rake db:migrate would solve any of my problems... or just create new problems... I only have sample data filling in with faker
Any ideas?
Is it possible to revert my file system back to a previous commit and start over? ... when I was green
Failures:
1) Micropost should create a new instance with valid attributes
Failure/Error: #user = Factory(:user)
ActiveRecord::StatementInvalid:
Could not find table 'users'
# ./spec/models/micropost_spec.rb:5:in `block (2 levels) in <top (required)>'
2) Micropost user associations should have a user attribute
Failure/Error: #user = Factory(:user)
ActiveRecord::StatementInvalid:
Could not find table 'users'
# ./spec/models/micropost_spec.rb:5:in `block (2 levels) in <top (required)>'
3) Micropost user associations should have the right associated user
Failure/Error: #user = Factory(:user)
ActiveRecord::StatementInvalid:
Could not find table 'users'
# ./spec/models/micropost_spec.rb:5:in `block (2 levels) in <top (required)>'
4) Micropost validations should have a user id
Failure/Error: #user = Factory(:user)
ActiveRecord::StatementInvalid:
Could not find table 'users'
# ./spec/models/micropost_spec.rb:5:in `block (2 levels) in <top (required)>'
5) Micropost validations should require nonblank content
Failure/Error: #user = Factory(:user)
ActiveRecord::StatementInvalid:
Could not find table 'users'
# ./spec/models/micropost_spec.rb:5:in `block (2 levels) in <top (required)>'
6) Micropost validations should reject long content
Failure/Error: #user = Factory(:user)
ActiveRecord::StatementInvalid:
Could not find table 'users'
# ./spec/models/micropost_spec.rb:5:in `block (2 levels) in <top (required)>'
Update 1:
I'm getting errors from 4 to 6 to 111 all with a recurring theme of
1) Micropost should create a new instance with valid attributes
Failure/Error: #user = Factory(:user)
ActiveRecord::StatementInvalid:
Could not find table 'users'
# ./spec/models/micropost_spec.rb:53:in `block (2 levels) in <top (required)>'
Specifically the "Could not find table 'users'" - I copied the code from the tutorial git for the micropost_spec.rb file but didn't seem to fix it- maybe someone can help direct me to what the table is referring to?
////////////////////////////////////// ORIGINAL BELOW ////////////////////////////////
I am working in the Ruby on Rails Tutorial lesson 11 and am trying to populate my db to show the microposts
when I did the rake db:populate command it gave me the following:
macbook:sample_app macbook$ rake db:populate
(in /Users/macbook/rails_screencast/sample_app)
db/test.sqlite3 already exists
db/test.sqlite3 already exists
db/development.sqlite3 already exists
-- create_table("microposts", {:force=>true})
-> 0.0090s
-- add_index("microposts", ["user_id"], {:name=>"index_microposts_on_user_id"})
-> 0.0074s
-- create_table("users", {:force=>true})
-> 0.0243s
-- add_index("users", ["email"], {:name=>"index_users_on_email", :unique=>true})
-> 0.0094s
-- initialize_schema_migrations_table()
-> 0.0167s
-- assume_migrated_upto_version(20110614132314, "db/migrate")
-> 0.0432s
rake aborted!
Validation failed: Email is invalid
I ran it a couple times and kept getting the same error... when I visited the site on a browser it was like none of my sample users were there...
require 'faker'
namespace :db do
desc "Fill database with sample data"
task :populate => :environment do
Rake::Task['db:reset'].invoke
admin = User.create!(:name => "Foo Bar",
:email => "foo#bar.com",
:password => "foobar",
:password_confirmation => "foobar")
admin.toggle!(:admin)
99.times do |n|
name = Faker::Name.name
email = "example-#{n+1}#railstutorial.org"
password = "password"
User.create!(:name => name,
:email => email,
:password => password,
:password_confirmation => password)
end
User.all(:limit => 6).each do |user|
50.times do
user.microposts.create!(:content => Faker::Lorem.sentence(5))
end
end
end
end
then I decided oh maybe rake db:reset will purge my sample database and I can run the populate again with fresh stuff... bad assumption
my test suite now shows:
Finished in 0.99915 seconds
111 examples, 111 failures
Now before I mess more stuff up I'm looking for some advice where to go next ...
Michael (author of the railstutorial.org) responded to my email request!
If you're missing a table when running the test suite, it's probably an indication that you need to run:
rake db:test:prepare
YUP!! YAYYYY
Finished in 4.82 seconds
108 examples, 0 failures
CAKE TIME!
The db:populate that you're showing does a db:reset itself, so doing it manually can't have caused any problem that wasn't already happening with the db:populate.
You can just delete your db/*.sqlite3 files and start from fresh. There's nothing obvious in that db:populate code which would explain why the email validation failed, you'd have to show the User model and the validations you have in there for us to diagnose that initial issue.

Namespaced controller causes error in Rails-3

I am using ActsAsTaggableOn to add tagging to my application. In addition to the features i get from this gem, I would also like to add a TagsController and basically treat tags as any other resource in my app.
I have created tags_controller.rb which contains
class ActsAsTaggableOn::TagsController < ApplicationController
# ...
end
and in my routes.rb i have added
resources :tags, :module => :acts_as_taggable_on
When I run rake routes i get
tags GET /tags(.:format) {:action=>"index", :controller=>"acts_as_taggable_on/tags"}
POST /tags(.:format) {:action=>"create", :controller=>"acts_as_taggable_on/tags"}
new_tag GET /tags/new(.:format) {:action=>"new", :controller=>"acts_as_taggable_on/tags"}
edit_tag GET /tags/:id/edit(.:format) {:action=>"edit", :controller=>"acts_as_taggable_on/tags"}
tag GET /tags/:id(.:format) {:action=>"show", :controller=>"acts_as_taggable_on/tags"}
PUT /tags/:id(.:format) {:action=>"update", :controller=>"acts_as_taggable_on/tags"}
DELETE /tags/:id(.:format) {:action=>"destroy", :controller=>"acts_as_taggable_on/tags"}
… which all looks reasonable to me.
However, when I hit localhost:3000/tags i get this error:
LoadError (Expected MyApp/tags_controller.rb to define TagsController)
If I try to evaluate ActsAsTaggableOn::TagsControllerin the console I get basically the same error:
LoadError: Expected MyApp/app/controllers/tags_controller.rb to define TagsController
from ~/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:492:in `load_missing_constant'
from ~/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:183:in `block in const_missing'
from ~/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `each'
from ~/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `const_missing'
from ~/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:503:in `load_missing_constant'
from ~/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:183:in `block in const_missing'
from ~/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `each'
from ~/.rvm/gems/ruby-1.9.2-p180/gems/activesupport-3.0.4/lib/active_support/dependencies.rb:181:in `const_missing'
from (irb):1
from ~/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.4/lib/rails/commands/console.rb:44:in `start'
from ~/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.4/lib/rails/commands/console.rb:8:in `start'
from ~/.rvm/gems/ruby-1.9.2-p180/gems/railties-3.0.4/lib/rails/commands.rb:23:in `'
from script/rails:6:in `require'
from script/rails:6:in `'
What am I doing wrong?
Rails expects modules and classes to be in their namespace's directory. So you should move your controller, views and helpers in an acts_as_taggable_on directory:
app/controllers/acts_as_taggable_on/tags_controller.rb
app/views/acts_as_taggable_on/tags/index.html.erb
etc.
I'm not sure why you want this namespace. If you only want to create REST actions on an existing model, you can generate a scaffold_controller. For example:
rails generate scaffold_controller Tag name:string
Michaël is right about the directory structure for namespaced controllers.
That being said, a controller does not have to be in the same namespace as a model. On the contrary, you can have a controller named SomeController working with a model named SomeModel. Have you already tried to drop the namespace from the controller class and see what goes wrong?

MongoMapper won't let me create an object

I'm just learning MongoDB and MongoMapper. This is on Rails 3.
I created a blog in app/models/blog.rb:
class Blog
include MongoMapper::Document
key :title, String, :required => true
key :body, Text
timestamps!
end
I go into the Rails console:
rails c
Loading development environment (Rails 3.0.0.beta)
ruby-1.9.1-p378 > b = Blog.new
NoMethodError: undefined method `from_mongo' for Text:Module
from /Users/jade/.rvm/gems/ruby-1.9.1-p378/gems/mongo_mapper-0.7.2/lib/mongo_mapper/plugins/keys.rb:323:in `get'
from /Users/jade/.rvm/gems/ruby-1.9.1-p378/gems/mongo_mapper-0.7.2/lib/mongo_mapper/plugins/keys.rb:269:in `read_key'
from /Users/jade/.rvm/gems/ruby-1.9.1-p378/gems/mongo_mapper-0.7.2/lib/mongo_mapper/plugins/keys.rb:224:in `[]'
from /Users/jade/.rvm/gems/ruby-1.9.1-p378/gems/mongo_mapper-0.7.2/lib/mongo_mapper/plugins/inspect.rb:7:in `block in inspect'
from /Users/jade/.rvm/gems/ruby-1.9.1-p378/gems/mongo_mapper-0.7.2/lib/mongo_mapper/plugins/inspect.rb:6:in `collect'
from /Users/jade/.rvm/gems/ruby-1.9.1-p378/gems/mongo_mapper-0.7.2/lib/mongo_mapper/plugins/inspect.rb:6:in `inspect'
from /Users/jade/.rvm/gems/ruby-1.9.1-p378/gems/railties-3.0.0.beta/lib/rails/commands/console.rb:47:in `start'
from /Users/jade/.rvm/gems/ruby-1.9.1-p378/gems/railties-3.0.0.beta/lib/rails/commands/console.rb:8:in `start'
from /Users/jade/.rvm/gems/ruby-1.9.1-p378/gems/railties-3.0.0.beta/lib/rails/commands.rb:34:in `<top (required)>'
from /Users/jade/code/farmerjade/script/rails:10:in `require'
from /Users/jade/code/farmerjade/script/rails:10:in `<main>'
Am I overlooking something really dumb, or is this something in my setup?
I'm using the mongo_mapper version you get by adding it to your Gemfile, so I'm wondering if it might be that. I'd appreciate any suggestions!
As I suspected, this was a silly mistake. I was using Text instead of String, and Mongo doesn't natively support Text as a key. If you define a from_mongo method, it would.
Thanks to DanP on IRC for pointing out my error.