Mongomapper: Embedded document does not work properly - ruby-on-rails-3

I don't know what's going on but I can't seem to find working a very small piece of code. I used mongomappper without embedded documents and everything went fine. Using an embedded document I hit the brick wall. I'm following the instructions on the mongomapper homepage using the Rails console:
Here are my models:
class Assessment
include Mongomapper::Document
many :sections
end
class Section
include MongoMapper::EmbeddedDocument
key :title, String
validates_presence_of :title
end
When I run:
a = Assessment.create(:sections => [ Section.new(:title => 'test') ] )
I will get the following output:
=> #<Assessment _id: BSON::ObjectId('4e71efce69a74c0fb6000002'), sections: nil>
I also tried with a = Assessment.new(), a.sections << Section.new(:title => "test")
but the same result.
Why is there nothing inside sections?

Including:
attr_accessible :sections
should make the create work (at it does for me). And you'll probably want to add:
validates_associated :sections
to make your Assessment validate the embedded Sections the way you'd probably expect.
Yeah, a couple years late but I just had to sort this problem out and Google brought me here.

Related

Rails 3 inherited_resources ignores 'defaults' setting

I'm using Inherited resources for my controllers. And now i have model:
class Sms < ActiveRecord::Base
end
And i want controller for it, where i make defaults:
class Admin::SmsesController < Admin::InheritedResources
defaults :resource_class => Sms,
:collection_name => 'smses',
:instance_name => 'sms'
end
but i can not understand, why it still trying to get "Smse" model:
NameError in Admin::SmsesController#index
uninitialized constant Smse
Pls help.
The problem is that Rails doesn't know that the plural of Sms is Smses. If you go to the Rails console you should see that:
> "Sms".pluralize
=> "Sms"
> "Smses".singularize
=> "Smse"
When faced with a plural it doesn't recognise, singularize just truncates the final "s", which is why your app is looking for a nonexistent Smse model.
You will save yourself a lot of headaches by configuring Rails to pluralize/singularize your models correctly. In the file config\initializers\inflections.rb you should find some examples of how to do this. What you want is:
ActiveSupport::Inflector.inflections do |inflect|
inflect.irregular 'sms', 'smses'
end
Then I don't think you should need to put the defaults option in there at all - it should all work out of the box.

Thinking sphinx not indexing belongs_to relationship properly in production but works fine in dev

I want to display the movies associated to a given author. On the author's page, I want users to be able to paginate, sort, and filter by keyword.
Everything works fine on my local machine. But, in production, the list of movies on the author's page is empty, and I can't figure out why. In production, in the console, I tested the following expressions, but no luck (always returns 0, while it returns values > 0 in dev):
ruby-1.9.2-p290 :042 > Movie.search(:with => {:author_ids => [6]}).count
=> 0
ruby-1.9.2-p290 :043 > Movie.search(:with => {:author_ids => 6}).count
=> 0
The weird thing is that I'm using a very similar code to display the movies associated to a topic on a topic's page, and it works great in development AND in production. For instance:
ruby-1.9.2-p290 :051 > Movie.search(:with => {:topic_ids => 2}, :per_page => 1000).count
=> 295
Here is how I define my Movie class:
class Movie < ActiveRecord::Base
belongs_to :author
has_many :topics
...
define_index('movie') do
...
has author(:id), :as => :author_ids,
:facet => true
has topics(:id), :as => :topic_ids,
:facet => true
...
end
...
end
And here is what my Author show controller looks like:
def show
#author = Author.find(params[:id])
keywords = params[:what] || ""
with_params[:author_ids] = [#author.id]
#movies = Movie.search(
keywords,
:with => with_params
)
end
This leads me to believe there is something wrong with the Sphinx index in production, but I'm not sure how to investigate further to find the root of the problem...
UPDATE: Following Pat's suggestion, I updated Sphinx and everything was solved (I upgraded from 0.9.8 to 0.9.10)! I was confused because Sphinx is NOT a Gem (even though a Sphinx gem exists)... So I had to go through the regular download, make, make install process.
I'll start with the obvious, but maybe this has already been tried - is the author_ids attribute something relatively new? Have you rebuilt (indexed and restarted) Sphinx since adding that attribute? rake ts:rebuild is the easy way to do that.
Update: It turns out updating Sphinx was the fix here - Alex can confirm which version, but I'm guessing 0.9.9 or better should do the trick.

Rails 3 Routing: Using 2 dynamic segments in path for one model

What I am trying to achieve is something similar to Github's way for routes. E.g. I have a project with the name 'question' results in the URL /hjuskewycz/question. So my goal is to have routes where the first segment is the username and the second the project's name.
I tried a couple of different approaches, this is the one I am stuck with right now:
scope ":username" do
resources :projects, :path => "" do
resources :pictures
end
end
Using
project_path :username => project.owner.username, :id => project.to_param
works as expected. However, it's tedious to always specify the username although it's always the owner's username. I would very much prefer
project_path(:id => project.to_param)
I know about default_url_options and url_for and I digged in the code. However, polymorphic_url doesn't use default_url_options.
I tried in routes.rb:
resources :projects, :path => "", :defaults => {:username => Proc.new { "just_testing" }}
since you can use a proc for constrains, but haven't got it working either.
I tried in project.rb
def to_param
"#{owner.username"/#{project.title}"
end
I spent already too much time on this problem and my current approach uses a convenience method to add the :username parameter. Nevertheless, I think using this method all over the place just to add an entry stinks (bad code smell). I wonder if there is a more elegant solution to this problem.
I think you should not make things complicated here, just use something like this:
In Routes.rb
match ':username/:projectname/' => 'projects#show_project' , :as => :show_project
and in project_controller, just define this
def show_project
#user =User.find_by_username(params[:username])
#project =Project.find_by_slug(params[:projectname])
end
Simpler is better, it saves time and easy to understand for others
You want to do something like this in your controller:
before_filter :set_username
def set_username
Rails.application.routes.default_url_options[:username] = #user.name
end

multiple image upload with dragonfly

i was trying for multiple image upload with dragonfly in rails3. i searched for some tutorials, but couldn't find any. i found a tutorial for multiple image upload with Carrierwave, but couldnt find luck with dragonfly .. any help please :)
Preface
Dragonfly itself can be used to manage media for your project in general, similar to paperclip. The question itself boils down to the multiple file upload within a rails application. The some tutorials on this topic available, which can easily be adapted to models using Dragonfly for storing specific files on them. I would suggest you look into those and try to adapt them for your project.
However, I can present a minimum example which i built for a rails 3.2 app currently in development, which isn't perfect (validation handling for example), but can give you some starting points.
Example
Just for reference, the essential idea is taken from here. This example is done with Rails 3.2.x.
Let's say you have a vacation database, where users may create trip reports on vacations they took. They may leave a small description, as well as some pictures.
Start out by building a simple ActiveRecord based model for the trips, lets just call it Trip for now:
class Trip < ActiveRecord::Base
has_many :trip_images
attr_accessible :description, :trip_images
end
As you can see, the model has trip images attached to it via a has_many association. Lets have a quick look at the TripImage model, which uses dragonfly for having the file stored in the content field:
class TripImage < ActiveRecord::Base
attr_accessible :content, :trip_id
belongs_to :trip_id
image_accessor :content
end
The trip image it self stores the file attachment. You may place any restrains within this model, e.g. file size or mime type.
Let's create a TripController which has a new and create action (you can generate this via scaffolding if you like, it is by far nothing fancy):
class TripController < ApplicationController
def new
#trip = Trip.new
end
def create
#trip = Trip.new(params[:template])
#create the images from the params
unless params[:images].nil?
params[:images].each do |image|
#trip.trip_images << TripImages.create(:content => image)
end
if #trip.save
[...]
end
end
Nothing special here, with the exception of creating the images from another entry than the params hash. this makes sense when looking at the the file upload field within the new.html.erb template file (or in the partial you use for the fields on the Trip model):
[...]
<%= f.file_field :trip_images, :name => 'images[]', :multiple => true %>
[...]
This should work for the moment, however, there are no limitations for the images on this right now. You can restrict the number of images on the server side via a custom validator on the Trip model:
class Trip < ActiveRecord::Base
has_many :trip_images
attr_accessible :description, :trip_images
validate :image_count_in_bounds, :on => :create
protected
def image_count_in_bounds
return if trip_images.blank?
errors.add("Only 10 images are allowed!") if trip_images.length > 10
end
end
I leave this up to you, but you could also use client side validations on the file field, the general idea would be to check the files upon changing the file field (in CoffeeScript):
jQuery ->
$('#file_field_id').change () ->
#disable the form
for file in this.files
#check each file
#enable the form
Summary
You can build a lot out of existing tutorials, as dragonfly does not behave that differently to other solutions when it comes to just to uploading files. However, if you'd like something fancier, I'd suggest jQuery Fileupload, as many others have before me.
Anyways, I hope I could provide some insight.

TDD: Rspec Ruby MongoDB/Ruby Mongo Driver

how can I use TDD with MongoDB as my second database?
Thanks
Edit:
Using Rspec or anything else that allows me to test it.
[Update]
With MongoMapper set up you can easily use the mongodb connection directly
mongodb = MongoMapper.database
collection = mongodb.collection("my_collection")
collection.find.first
=> {"_id"=>BSON::ObjectId('4e43dfc75d1e1e0001000001'), "key1"=>"val1" }
this other SO Q/A is even more direct, using javascript functions like MongoMapper.database.eval(Mongo::Code.new('function(){ return 11 + 6; })
[/update]
I have such a polyglot architecture, some models with postgresql, others as mongo documents. I'm not really sure what you're asking, so I'll jump straight in and post most my configuration here. It includes my hacks, you probably find more beautiful config elsewhere.
I put the setup in a gist
https://gist.github.com/957341
OK, so here's a document with embedded document, then the spec. I wrote the specs one by one, so they're kinda test driven.
class MyDocument
include MongoMapper::Document
key :title, String
key :published_at, Time, :index => true
key :collaborators, Array
many :my_embedded_documents
end
class MyEmbeddedDocument
include MongoMapper::EmbeddedDocument
key :title, String
key :author, String
embedded_in :my_document
end
the spec
require "spec_helper"
describe MyDocument do
before do
#md = MyDocument.create(:title => "Example", :collaborators => ["mongomapper", "rspec", "oma"] )
end
it "should have title" do
found = MyDocument.find(#md.id)
found.title.should == "Example"
end
it "should have two my_documents" do
MyDocument.create
MyDocument.count.should == 2
end
it "should be able to fetch embedded documents" do
#md.my_embedded_documents << MyEmbeddedDocument.new(:title => "The King", :name => "Elvis Presley")
#md.my_embedded_documents.build(:title => "Embedded example", :name => "Embeddo")
#md.save!
MyDocument.where(:title => "Example").first.should == #md #findMyEmbeddedDocument.count.should == 2
end
end
spec_helper.rb
RSpec.configure do |config|
#...
config.after(:each) do
MongoMapper.database.collections.each(&:remove)
end
end
I don't know what you wanted for answers, but I hope this will be of help to somebody.
From what I can gather, it doesn't appear that your app is sticking to the rails MVC paradigm with its use of this secondary database that apparently doesn't store model data.
I would recommend taking the auxiliary parts of the app that depend on mongo and sticking them into a library. You can make this a gem if it makes sense to use it elsewhere. Then, create a testsuite for the logic of the library using standard testing tools, and integrate into your app either with a simple require, or some directives (depending on what it dies and how you intend to use it).