Mongoid equivalent of ActiveRecord's `serialize` method - ruby

hope the title's pretty self-explanatory.
I'm using mongoid as my ORM for a Rails app, and I was wondering if anybody knew if it has an equivalent to ActiveRecord's serialize method. I've looked through the mongoid documentation but haven't been able to find anything yet.
Here's an example of the model:
class Foo
include Mongoid::Document
field :params, type: String
serialize :params # method from ActiveRecord
end
Thanks in advance!

You don't need to serialize with MongoDB as far as you can store in fields Arrays and Hashes.
field :hash_params, type: Hash
field :array_params, type: Array

Sometimes you need use the Value Object pattern and the same function like composed_of, some people wants to deprecate this function in the future and than you want to use serialize of standard active record. Mongoid provide the same functionality to create Value object avoid the serialize method look , you can provide your custom serialization here http://mongoid.org/en/mongoid/docs/documents.html#custom_fields:
class Foo
include Mongoid::Document
field :params, type: String
field :custom_params , type: MyCustomParamsType
end

Related

Returning an array graphQL

I'm currently trying to learn GraphQL but running into a problem. The problem is possibly not understanding the right way in writing my types. When I had my user type as
module Types
UserType = GraphQL::ObjectType.define do
name 'User'
field :id, !types.ID
field :username, !types.String
field :email, !types.String, property: :email_address
field :workspaces, types[Types::WorkspaceType]
end
end
I'm able to return an array of workspaces without a problem. Now the problem comes when I try to return an array of users that are associated with that workspace. My workspace type looks like this
class Types::WorkspaceType < Types::BaseObject
field :id, ID, null: false
field :user_id, ID, null: false
field :name, String, null: false
field :members, types[Types::UserType]
end
When I try to run the query in fetching the workspace I'm getting an error that says
"error": {
"message": "undefined local variable or method `types' for Types::UserType:Class",
The backend I'm using is Ruby on Rails. For those with some experience with GraphQL, I would love feedback in what I'm doing wrong and also what is the right way in connecting types between each model. If there are any extra information you'll need or want clarification with please feel free to ask.
Thank you.
The graphql gem has two different "styles" of declaring GraphQL objects using a Ruby DSL (and it can also directly import the GraphQL schema language). The older style (now expunged from the docs) uses GraphQL::ObjectType.define, and needs to qualify most references with the types syntax. The newer style uses Ruby class inheritance, and doesn't use types.
In short: I think your code will work if you just change the last field definition to
field :members, [Types::UserType]

save Hash to a column (type: text) in database by serialization, why is it saved YAML

We are trying to serialize an attribute called differences in order to save the value of this attribute as a Hash into database. The type of differences is text. it used to be saved as Hash in the database. But recently we found out it is saved yaml. is there any way to prevent it saving as yaml?
Class A < ActiveRecord::Base
has_many :bs
serialize :differences
def diff(other)
b_diffs = {}
bs.zip(other.bs).each do |a,b|
b_diffs.merge!(:bs => a.diff?(b)
end
end
def diff_against_last_a
last_a = ....
self.differences = last_a.diff(self)
end
end
Any suggestion?
EDIT:
my problem is i can't retrieve differences as Hash.
Interestingly, when i check on console, it is saved as yaml, and retrieved as yaml. and then i rerun the the method diff(other) and save the result to differeces, it shows as Hash and i can retrieve Hash. But it doesn;t work this way when running on my app.
I think the problem here is the serialized data are no longer returned Hash.
UPDATE:
So i found out under the development environment, there is such a problem. But in production and staging (we use heroku), it practises fine. so We'll consider it ok then.
In addition to my comment, here is the official description:
If you have an attribute that needs to be saved to the database as an
object, and retrieved as the same object, then specify the name of
that attribute using this method and it will be handled automatically.
The serialization is done through YAML. If class_name is specified,
the serialized object must be of that class on retrieval or
SerializationTypeMismatch will be raised.
source: http://apidock.com/rails/ActiveRecord/Base/serialize/class
In layman's terms "When Rails serializes a hash to save in the db, all it does is convert it to YAML so that it can be stored as a string."
As the last line of official description reads, you have define the class of retrieval. Hash in your case. So declare serialize like this:
serialize :differences, Hash

Can I remove an embedded document in Mongoid without persisting?

Definitely related to this question, but since there was no clear answer, I feel like I should ask again. Is there any way to remove an embedded document from a Mongoid embeds_many relationship, without persisting?
I want to modify the array of embedded documents in-memory - and then persist all changes with a single UPDATE operation. Specifically, I'd like to:
Modify arrays of embedded documents (add embedded doc / remove embedded doc / edit embedded doc / etc).
Possibly make other changes to the TLD.
Persist all changes with a single database call.
It is possible to remove an embedded document using Mongoid without saving. The trick is to make your changes from the parent object using assign_attributes. For exmaple:
class MyParent
include Mongoid::Document
field :name, type: String
embeds_many :my_children
def remove_my_child(child)
assign_attributes(my_children: my_children.select { |c| c != child })
end
end
class MyChild
include Mongoid::Document
embedded_in :my_parent
def remove
parent.remove_my_child(self)
end
end
my_parent = MyParent.first
my_first_child = my_parent.my_children.first
# no mongo queries are executed
my_first_child.remove
# now we can make another change with no query executed
my_parent.name = 'foo'
# and finally we can save the whole thing in one query which is the
# reason we used an embedded document in the first place, right?
my_parent.save!
After two more years of using Mongoid, I've learned there's no operator for what I was trying to achieve. Removing an embedded document with Mongoid always results in a database call.
In situations like this one, it's easier to bypass Mongoid and use the mongo-ruby-driver directly.
Try mongoid's
update_all()
Documentation
Ex: If I wanted to make all my users Joe
User.update_all(name: 'Joe')
will behave exactly as you would expect.

Mongoid and Full_text search issue

I have been working on rails project, which had been made using noSql(Mongoid). Every thing is running fine.The issue is I want to add.. full text search here also. I had been using this gems for this...
gem 'mongoid_fulltext'
and my model file looks like this..
class Keyword
include Mongoid::Document
include Mongoid::FullTextSearch
field :name, type:String
#index :name, unique: true
embeds_many :posts
validates_presence_of :name
validates_uniqueness_of :name
fulltext_search_in :name, :index_name => 'name_index'
end
and in controller.
#keywords = Keyword.fulltext_search(params[:search], :index => 'name_index')
and then #keywords always returns an empty array always.
Thanks
Awieet
Apart from what I'm assuming are formatting errors, the only mistake I can find is that you seem to be naming the index manually.
Maybe in your fulltext_search call you should use :index_name => 'name_index' instead of :index => 'name_index'.
I'd advise just not messing with the default name of the index though, and removing that argument entirely from the method call.
Also, were the records persisted before you added the mongoid_fulltext gem? If so you'll need to call the update_ngram_index method on the Class object (or each instance) to add them to the index.
Other than that, have you checked out the mongoid_search gem as an alternative to mongoid_fulltext?
https://github.com/mauriciozaffari/mongoid_search
I've tried both and find find that this one has a much cleaner implementation and interface. Then again, I only use fulltext search sparingly. You may be using fulltext search more than I, and I'm not sure what the differences are feature-wise, but worth a look.
Hope that helps.

Tire (an elasticsearch client) needs pagination to perform an import, how do I do this with a custom model?

If I have a simple class like:
class Article
include Tire::Model::Persistence
property :title, :analyzer => 'snowball'
property :published_on, :type => 'date'
property :tags, :default => [], :analyzer => 'keyword'
end
It seems that I can only perform Article.import if there is a pagination method. But because this is a custom persistent model and I'm not using ActiveRecord, I am not able to use WillPaginate or Kaminari. So is there a custom method I can create to support pagination, and if so what requirements must it meet?
Looking at import method (https://github.com/karmi/tire/blob/master/lib/tire/index.rb#L103-124) looks like there are two options.
Create a paginate method that gets per_page and page parameters in options hash.
Create a map enumerator that returns all documents.
Then looking at bulk_store https://github.com/karmi/tire/blob/master/lib/tire/index.rb#L67-79 you have meet some other requirements for the document itself. Look at methods https://github.com/karmi/tire/blob/master/lib/tire/index.rb#L67-79
I was using mongoid as well and I found that I needed to require 'will_paginate/array' within my environment .rb in order to pull in the records. I don't think you need to use it after that but will_paginate helps with the import process.

Resources