How do you display all values in an object? - ruby

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.

Related

How to run method of inherited class in mongodb?

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

Updating in MongoDB without first having to pull a Mongoid object?

When performing queries I can go through Mongoid:
product_obj = Product.where(
_id: "58f876f683c336eec88e9db5"
).first # => #<Product _id: 58f876f683c336eec88e9db5, created_at: nil, updated_at: nil, sku: "123", name: "Some text", ...)
​
or I can circumvent it:
product_hsh = Product.collection.find( {
_id: BSON::ObjectId.from_string("58f876f683c336eec88e9db5")
}, {
projection: {
_id: 1,
name: 1
}
} ).first # => {"_id"=>BSON::ObjectId('58f876f683c336eec88e9db5'), "name"=>"Some text"}
I prefer to circumvent, because it performs better; I can limit which fields to get in the response.
My problem, however, is how to further work with the returned product. The response is a hash, not an object, so if I have to update it I need to pull it through Mongoid anyway, and thereby the performance gains are gone:
Product.find(product_hsh["_id"]).update_attribute(:name, "Some other text")
My question is: how do I update without first having to pull a Mongoid object?
You don't need to pull/fetch at all. You can just send the $set commands directly:
Product.where(id: product_hsh["_id"]).update_all(name: "Some other text")

Create a Model Scope using hash attribute

I am using mongoid-history gem and mongoid in Ruby. I am actually linking the mongo history to a model called SocialPost, so i can make something like.
history = current_user.social_posts.history_tracks
Now i need to filter this 'history' with a scope or a method that filter attribute 'association_chain' from history tracker model, but 'history_tracks' attributes are made in this way:
<HistoryTracker _id: 57bdc1cb65e59325ae000001, created_at: 2016-08-24 15:48:27 UTC, updated_at: 2016-08-24 15:48:27 UTC, association_chain: [{"name"=>"SocialPost", "id"=>BSON::ObjectId('57ac8b0f65e5930944000000')}], modified: {"facebook_likes_count"=>2594213, "tweeter_followers_count"=>0}, original: {}, version: 1, action: "update", scope: "social_post", modifier_id: nil>
So, how i can create a search in my HistoryTracker model that allow me to search a specific group of ids inside association_chain, something like this:
HistoryTracker.where(:association_chain.in => {"name"=>"SocialPost", "id"=>[GROUPS OF IDS TO SEARCH]}
UPDATE using $elemMatch
#test case multiple social_id: empty result
HistoryTracker.any_in({:association_chain.elem_match => [{name: 'SocialPost', :id.in => social_ids}] })
#test case 1 social_id: match result
HistoryTracker.any_in({:association_chain.elem_match => [{name: 'SocialPost', :id => social_ids.first}] })
I found already a posible solution. The elemMatch should be constructed grouped with ids you need to collect, so this is what i did:
social_ids = [BSON::ObjectId('...1'), BSON::ObjectId('...2'), BSON::ObjectId('...3')]
#reorder the ids with the extra hash elements
a = []
social_ids.each do |id_bson|
a << {name: 'SocialPost', id: id_bson}
end
And now you create the 'QUERY'
HistoryTracker.any_in({:association_chain.elem_match => a})

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.

Mongoid: Save an array of strings throws TypeError?

What am I doing wrong? I have this Mongoid-based model:
class ReadableThing
include Mongoid::Document
field :shop, type: Integer
field :user, type: Integer
field :title, type: String
field :s_title, type: String
field :s_desc, type: String
field :is_part, type: Boolean
field :pieces, type: Array
def self.with_shop_only(shop, with_parts)
ReadableThing.where(shop_id: shop, user: nil, is_part: with_parts)
end
def self.with_shop_and_user(shop, user_id, with_parts)
ReadableThing.where(brokerage_shop_id: shop, user: user_id, is_part: with_parts)
end
end
and when running this code:
ReadableThing.create({
shop: 2,
user: nil,
title: "Ooohh samples",
s_title: "SPL",
s_desc: nil,
is_part: true,
pieces: ["this","is","a","sample"],
})
I get this error:
TypeError: no implicit conversion of String into Integer
I've been able to track the thing down to the "pieces" array, everything works just perfect without it. I can't, though, figure out what I'm doing wrong.
Can anyone please lend me a hand here?

Resources