How to run method of inherited class in mongodb? - ruby

For example, I created ChildClass inherited from BaseClass below:
class BaseClass
end
First child class
class ChildClass1 < BaseClass
end
Or another
class ChildClass2 < BaseClass
end
When worked with BaseClass
It work as normal.
But when work with ChildClass 1 or 2,
I cannot do childclass1.count or childclass1.first
Errors as follow: (when working with child class after saved as show here)
[2] pry(#<TodosController>)> #todo = "Todo::TodoM#{$xvars["user_id"].to_s}".constantize.new
=> #<Todo::TodoM5ca1157c51d2f56bc4d5e379 _id: 5ca45c5651d2f5988c2ef5fa, created_at: nil, updated_at: nil, user_id: nil, title: nil, completed: nil, due: nil, detail: nil, image: nil, member: nil, status: nil, _type: "Todo::TodoM5ca1157c51d2f56bc4d5e379">
[3] pry(#<TodosController>)> #todo = "Todo::TodoM#{$xvars["user_id"].to_s}".constantize.new(
[3] pry(#<TodosController>)* title: $xvars["form_todo"]["title"],
[3] pry(#<TodosController>)* user_id: $xvars["user_id"])
=> #<Todo::TodoM5ca1157c51d2f56bc4d5e379 _id: 5ca45ca351d2f5988c2ef5fb, created_at: nil, updated_at: nil, user_id: BSON::ObjectId('5ca1157c51d2f56bc4d5e379'), title: "sdfsdf", completed: nil, due: nil, detail: nil, image: nil, member: nil, status: nil, _type: "Todo::TodoM5ca1157c51d2f56bc4d5e379">
[4] pry(#<TodosController>)> #todo.save!
MONGODB | localhost:27017 | todo2_development.insert | STARTED | {"insert"=>"todos", "ordered"=>true, "lsid"=>{"id"=><BSON::Binary:0x70237914801960 type=uuid data=0x0c897c8df79a4052...>}, "documents"=>[{"_id"=>BSON::ObjectId('5ca45ca351d2f5988c2ef5fb'), "_type"=>"Todo::TodoM5ca1157c51d2f56bc4d5e379", "title"=>"sdfs...
MONGODB | localhost:27017 | todo2_development.insert | SUCCEEDED | 0.006s
=> true
[5] pry(#<TodosController>)> #todo.first
NoMethodError: undefined method `first' for #<Todo::TodoM5ca1157c51d2f56bc4d5e379:0x00007fc31453c828>
from (pry):6:in `create'
[6] pry(#<TodosController>)> #todo
=> #<Todo::TodoM5ca1157c51d2f56bc4d5e379 _id: 5ca45ca351d2f5988c2ef5fb, created_at: 2019-04-03 07:11:48 UTC, updated_at: 2019-04-03 07:11:48 UTC, user_id: BSON::ObjectId('5ca1157c51d2f56bc4d5e379'), title: "sdfsdf", completed: nil, due: nil, detail: nil, image: nil, member: nil, status: nil, _type: "Todo::TodoM5ca1157c51d2f56bc4d5e379">
[7] pry(#<TodosController>)> #todo.save!
=> true
[8] pry(#<TodosController>)> #todo.count
NoMethodError: undefined method `count' for #<Todo::TodoM5ca1157c51d2f56bc4d5e379:0x00007fc31453c828>
from (pry):9:in `create'
[9] pry(#<TodosController>)> #todo.first
NoMethodError: undefined method `first' for #<Todo::TodoM5ca1157c51d2f56bc4d5e379:0x00007fc31453c828>
from (pry):10:in `create'
[10] pry(#<TodosController>)> #todo.first
NoMethodError: undefined method `first' for #<Todo::TodoM5ca1157c51d2f56bc4d5e379:0x00007fc31453c828>
from (pry):11:in `create'
[11] pry(#<TodosController>)> #todo.class
=> Todo::TodoM5ca1157c51d2f56bc4d5e379
What did I do wrong?
(Yes I see error from 'create' but it saved! as shown)
{
"_id": ObjectId("5ca45ca351d2f5988c2ef5fb"),
"_type": "Todo::TodoM5ca1157c51d2f56bc4d5e379",
"title": "sdfsdf",
"user_id": ObjectId("5ca1157c51d2f56bc4d5e379"),
"updated_at": new Date(1554275508224),
"created_at": new Date(1554275508224)
}

I found ChildClass will work like BaseClass. The reason that not work in the beginning because user_id was nil.
The others issue is the way mongodb handle its subclass as internally as another type of data in it's BaseClass! even though we put namespace when created. What I surprised was the mongodb response namespace from rails is different by created another collection(table) as easily understand (and that what I first looking for) instead of hidden as another _type (field) that make me confused at first. So I like to note here for newbie.
instead of something I expected below as another collection

Related

rspec expect symbol not equal to created object

I wrote a test for controll with rspec:
it "populates an array of books" do
book = FactoryGirl.create(:book)
get :index
expect(:books).to eql([book])
end
books_controller.rb
def index
#books = Book.all.order("created_at DESC")
end
books.rb
FactoryGirl.define do
factory :book do |f|
f.name { Faker::Book.title }
f.author { Faker::Book.author }
f.press { Faker::Book.publisher }
f.cover { fixture_file_upload(Rails.root.join('spec', 'photos', 'testcover.jpg'), 'image/png') }
end
end
Run bin/rake spec, the result is:
1) BooksController GET #index populates an array of books
Failure/Error: expect(:books).to eql([book])
expected: [#<Book id: 1, name: "The Waste Land", author: "谢靖琪", isbn: nil, press: "University of Chicago Press"...e: "image/png", cover_file_size: 104531, cover_updated_at: "2016-08-26 04:00:19", page_number: nil>]
got: :books
(compared using eql?)
Diff:
## -1,2 +1,2 ##
-[#<Book id: 1, name: "The Waste Land", author: "谢靖琪", isbn: nil, press: "University of Chicago Press", description: nil, grade_level: nil, lexile_level: nil, douban_link: nil, scholastic_link: nil, created_at: "2016-08-26 04:00:19", updated_at: "2016-08-26 04:00:19", cover_file_name: "fcbcb7417dbc88827d16765a.jpg", cover_content_type: "image/png", cover_file_size: 104531, cover_updated_at: "2016-08-26 04:00:19", page_number: nil>]
+:books
They are not equal. It seems that the first expected result, '...' is an abbreviation. How can I fix it?
I think what you want is
expect(assigns(:books)).to eq([book])

How to access form object parameters in active admin

Really hope this is actually possible but I can't seem to access my forms parameters to send with my custom action
My aim here is for a user to fill in their form, click on a Preview button that will show them what their post will look like, i have created the view which is fine, just passing the parameters is an issue.
This is my current form
# Create Blog Post
form do |f|
inputs 'Blog' do
f.semantic_errors
f.input :title
f.input :category_id, as: :select, collection: Category.all
f.input :comments, as: :text, input_html: { rows: 10, cols: 10 }
f.input :published, as: :boolean
end
inputs 'Submit' do
f.actions do
f.action :submit
f.action :cancel
f.action :reset
li do
link_to 'Preview', preview_my_admin_panel_posts_path(post: { title: "test", comments: 'comments', category_id: '1' }) # Hardcoded for now
end
end
end
end
# Collection Action to handle object
collection_action :preview, method: :get do
#post = Post.new(permitted_params[:post])
end
So with everything the way it is (hardcoded) the params are passed through and output in my preview view, but as soon as i try accessing the forms object/params nothing gets passed th
# Console Output
1 - link_to 'Preview', preview_my_admin_panel_posts_path(post: { title: f.object.title, comments: f.object.comments, category_id: f.object.category_id})
#<Post:0x007f8bbe1fc4c0 id: nil, title: "", comments: "", category_id: nil, slug: nil, published: 0, created_at: nil, updated_at: nil>
2 - link_to 'Preview', preview_my_admin_panel_posts_path(post: { title: f.title, comments: f.comments, category_id: f.category_id })
# Console Output
#<Post:0x007f8bbe1fc4c0 id: nil, title: nil, comments: nil, category_id: nil, slug: nil, published: 0, created_at: nil, updated_at: nil>
3 - link_to 'Preview', preview_my_admin_panel_posts_path(#post)
# Console Output
#<Post:0x007f8bbe1fc4c0 id: nil, title: nil, comments: nil, category_id: nil, slug: nil, published: 0, created_at: nil, updated_at: nil>
Not sure where else to go with this, f.object.param seems close but passing through empty strings? has anyone done this before ?
If anyone has an alternative solution would love to hear it.
Thanks
Update
When outputting params to the console i get this returned
{"action"=>"preview", "controller"=>"my_admin_panel/posts"}
Are you trying to create a post? When you load this page the fields do not have any value thus the link will not load any parameter(you can inspect element on the preview link and see that the link does not have any parameter).
One way is to use JavaScript to catch the value before the link has routed in controller.

How to test Rspec For controller,

How to Rectify this error in RSpec for Controller,
1) SellersController GET index find the Activity
Failure/Error: assigns(:activity).should eq([activity])
expected: [#<Activity id: 65, transactable_type: "admin", transactable_id: 1, action_type: "seller", user_id: 1, is_approved: false, approved_by: nil, created_at: "2012-04-09 11:02:17", updated_at: "2012-04-09 11:02:17", associatable_type: nil, associatable_id: nil>]
got: nil
(compared using ==)
Seller_rspec.rb
describe "GET index" do
it "find the Activity" do
activity = Activity.create!(:transactable_type=>"admin",:transactable_id=>1,:action_type=>"seller",:user_id =>1,:is_approved=>0)
get :index,{:is_approved => activity.to_param,:user_id=>1,:approved_by=>"admin"}
assigns(:activity).should eq([activity])
end
In controller
def index
#activities=Activity.find(:all,:select => 'DISTINCT transactable_type,transactable_id,action_type,is_approved,approved_by',:conditions=>["is_approved= ? and user_id=? and approved_by IS NULL",false,current_user.id])
end
You are putting a code into controller which should go to the model. Create a method or scope in Activity model like:
def self.find_not_approved(current_user_id)
find(:all,
:select => 'DISTINCT transactable_type,transactable_id,action_type,is_approved,approved_by',
:conditions= ["is_approved= ? and user_id=? and approved_by IS NULL",
false,
current_user_id])
end
So you can just have in controller (I've made up the method name):
def index
#activities = Activity.find_not_appoved(current_user.id)
end
And just to anser your question, it should be assigns(:activities).should eq([activity]) not assigns(:activity).should eq([activity]) - as your are checking #activities variable in controller not, #activity.

How do you display all values in an object?

This is a Mongoid object, but I think it applies for all objects. How do I split up #product into key, value pairs when #product looks like this:
#<Product _id: 4e7cd178e66de72d70000010, _type: nil,
created_at: 2011-09-23 18:35:36 UTC,
updated_at: 2011-09-23 18:35:36 UTC, brand: "crystalrock",
name: "Crazy Fool Specialty Tank", retailer: nil, model: nil,
sku: nil store: {"id"=>"36033", "name"=>"Ed Hardy"},
product_id: "684", sku_number: "D9WAFDCR", category_primary: "Tanks">
I would think it would be a object method, but I don't see one that works.
It looks like #product.attributes is a Mongoid method that works.

Attribute Not Being Added to Object

I'm trying to add an attribute to a model object. Direct access works but when I print the entire object or encode it into JSON, that attribute is left out. Can someone tell me what I'm doing wrong?
Here is my rails console output:
irb(main):010:0> b=ChatMessage.new(:user_id=>4,:room_id=>1,:message=>"Hello World")
=> #<ChatMessage id: nil, room_id: 1, user_id: 4, message: "Hello World", created_at: nil, updated_at: nil>
irb(main):011:0> b.sender_nickname="bbb"
=> "bbb"
irb(main):012:0> b.sender_nickname
=> "bbb"
irb(main):013:0> b
=> #<ChatMessage id: nil, room_id: 1, user_id: 4, message: "Hello World", created_at: nil, updated_at: nil>
Here is my model code:
class ChatMessage < ActiveRecord::Base
attr_accessor :sender_nickname
def self.get_last_message_id
last_message=ChatMessage.all.last
last_message.nil? ? 0 : last_message.id
end
def self.get_all_messages_after(room_id,message_id)
ChatMessage.where("room_id = ? AND id > ?",room_id,message_id)
end
end
edit:
Here is the migration file for chat_messages table.
I'm not really looking to save sender_nickname. So it's more like a virtual attribute (but is still in db through association). And I might need to add other attributes later that aren't in the db. Is it possible to do it without using association?
def self.up
create_table :chat_messages do |t|
t.integer :room_id
t.integer :user_id
t.string :message
t.timestamps
end
end
as far as I know to_json will only take the attributes in the model and serialize (as in chat_message.attributes, not attr_accessor).
You properbly got a sender, or user model, or anything like that.
What I would do is to make a relation to the sender, user or what its called, with a belong_to, and then use this code to convert it to json:
chat_message.to_json(:include => { :sender => { :only => :nickname } })
It may also work with you code, and then just:
chat_message.to_json(:include => { :sender_nickname })
There also some documentation here: http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html
Hope it helps :)

Resources