Rails model serialize before storing - ruby-on-rails

I've been trying to serialize a column before I put it in the database. I wanted to do the following in my model:
class SearchResult < ActiveRecord::Base
serialize :data
end
...but it wouldn't serialize when I save. So I resorted to this:
class SearchResult < ActiveRecord::Base
before_save :serialize_data
private
def serialize_data
self.data = YAML.dump self.data
end
end
This works. But, is there any reason why the top code doesn't work (it's much neater), or do I need to declare the serialize method? It doesn't throw any errors, but doesn't do what I hoped it would do either.

Have you tried:
class SearchResult < ActiveRecord::Base
serialize :data, Hash
end

What about
class SearchResult < ActiveRecord::Base
store :data, accessors: [:data_help]
end

Related

Rails ignore coder in model

I need to run a rake task to migrate data in my model
class Translation < ApplicationRecord
store :body, accessors: [:object_body], coder: YAML
belongs_to :team
end
and need to access body as text.
I don't want to remove the coder part since a lot of logic relies on that.
Can I access body without decoding to a ruby object?
Just add a new method on the model.
class Translation < ApplicationRecord
store :body, accessors: [:object_body], coder: YAML
belongs_to :team
def raw_body
read_attribute_before_type_cast('body')
end
end
read_attribute_before_type_cast should work. It will return the value before typecasting or deserialization.
raw_body = obj.read_attribute_before_type_cast(:body)

Iterate over STI list in rails 4

I have two sub models, called: Service and Product that inherits from ProductBase. And I have another model to consume it. Acquire that have many AcquireBasket. Check out my code:
product_base.rb:
class ProductBase < ActiveRecord::Base
extend ::EnumerateIt
include Searchable
self.table_name = 'products'
end
product.rb:
class Product < ProductBase
default_scope { where(kind: ProductKind::PRODUCT) }
def initialize(attributes = {})
super(attributes)
self.kind = ProductKind::PRODUCT
self.status = ProductStatus::DRAFT
end
end
service.rb:
class Service < ProductBase
default_scope { where(kind: ProductKind::SERVICE) }
def initialize(attributes = {})
super(attributes)
self.kind = ProductKind::SERVICE
self.status = ProductStatus::DRAFT
end
end
acquire_basket.rb:
class AcquireBasket < ActiveRecord::Base
extend ::EnumerateIt
belongs_to :acquire
belongs_to :product
end
In some part of my project, I get a list (acquire baskets) of both models, Service and Product. And I need to check if I have services inside of it.
My code to check was:
def services_in?(acquire)
acquire.baskets.map(&:product).detect(&:service?)
end
The code works, ONLY if I pass services first, and products after!! Or if I have only one of them.
You should be able to utilize the descendents method to iterate over all of the subclasses
I can't find the answer in blog post around the world, so I will share with you:
class AcquireBasket < ActiveRecord::Base
extend ::EnumerateIt
belongs_to :acquire
belongs_to :product, class_name: 'ProductBase'
end
The problem was, when I try to find (lazily) in a ActiveRecord::Relation, Rails lookup (I think) to just Product model. And It can't find other type models inside of it. So using this typo I put it to work.

active model serializer with virtual attribute - Rails 4

I am currently making API with RoR, and I need to create an object with virtual attributes and associated object.
The problem is that serializer does not kick in when I return an object with virtual attribute.
Here is the returned object from foo_controller
{
:id=>280,
:virtual=>"y8st07ef7u"
:user_id=>280
}
:virtual is a virtual attribute and user_id is an id of associated table - User.
My goal is to make this
{
:id=>280,
:virtual=>"y8st07ef7u",
:user=>{
:id=>280,
:name=>'foo'
}
}
Foo_controller setting
class Api::V1::FoosController < ApplicationController
foos = Foo.all
foos.each do |foo|
foo.set_attribute('y8st07ef7u')
end
render json: foos.to_json(:methods => :virtual), status: 200
end
Foo_model setting
class Foo < ActiveRecord::Base
belongs_to :user
attr_accessor:virtual
def set_attribute(path)
self.virtual = path
end
end
Foo_serializer setting
class FooSerializer < ActiveModel::Serializer
attributes :id, :virtual
has_one :user
end
Foo migration setting
class CreateFoos < ActiveRecord::Migration
def change
create_table :foo do |t|
t.references :user
end
end
end
user model
class User < ActiveRecord::Base
has_many :foos
end
user serializer
class UserSerializer < ActiveModel::Serializer
attributes :id, :name
belongs_to :foo
end
When I replace "foo.to_json(:methods => :virtual)" in foo_controller with "foos", serializer kicks in and I get a user object inside the returned json instead of user_id, but :virtual is not in the json.
Are there any ways I can get an object with both virtual attributes and associated object using active model serializer.
Thank you in advance for your help!
I figured out. It was very simple.
I just had to add ":virtual" to attributes in the foo_serializer and replace "foo.to_json(:methods =>:virtual)" with just "foos"

Mount_upload on dynamic field with carrierwave

I have a model named CustomFields that belongs to a main class (that has_many :custom_fields). This model has the attributes contents and datatype. I want the contents to be either a string or a uploader using carrierwave, according to the datatype of the object. I've done the following:
class CustomField < ActiveRecord::Base
after_initialize :set_uploader
def set_uploader
if self.datatype == 'file'
CustomField.mount_uploader :contents, ImageUploader
end
end
end
It's not working because it's turning all the object's contents into uploaders, not only the 'file' datatype. How can I solve that?
Just a guess:
class CustomField < ActiveRecord::Base
mount_uploader :image, ImageUploader, if: :file?
def file?
self.datatype == 'file'
end
end

Conflict between Picture model and Ckeditor::Picture model

In my existing Rails project, I create Picture model.
class Picture < ActiveRecord::Base
belongs_to :user
end
And then, when adding Ckeditor to my project, I have to create another Picture model under ckeditor directory like this
class Ckeditor::Picture < Ckeditor::Asset
...
end
In my user model, I have this association
class User < ActiveRecord::Base
has_many :pictures
end
However, I cannot use user.pictures. Whenever I make this statement, the following error comes up:
Expected /home/xxx/app/models/ckeditor/picture.rb to define Picture
How can I solve this issue?
try:
class User < ActiveRecord::Base
has_many :pictures,:class_name=> "::Picture"
end
I'm not sure but maybe:
module Ckeditor
class Picture < Ckeditor::Asset
...
end
end
I managed to resolve my issue by renaming the Picture class into UserPicture and use table_name to set its corresponding table in database. And then in User model:
has_many :pictures, class_name: 'UserPicture'
Simple:
1) rename models/ckeditor/picture.rb to models/ckeditor/epicture.rb
2) in models/ckeditor/epicture.rb change to this:
class Ckeditor::Epicture < Ckeditor::Asset
has_attached_file :data,
url: "/ckeditor_assets/epictures/:id/:style_:basename.:extension",
path: ":rails_root/public/ckeditor_assets/epictures/:id/
3) in config/initializers/ckeditor.rb uncomment row and change to this:
config.picture_model { Ckeditor::Epicture }
4) for correct work in _asset.html.erb change bug:
polymorphic_path(asset, format: :json) to picture_path(asset)
in my case dir of this file
\usr\local\rvm\gems\ruby-1.9.3-p545\gems\ckeditor-4.1.2\app\views\ckeditor\shared\_asset.html.erb
Restart server.
Work's fine!
You can change Dafault Picture Model Name in config/initializers/ckeditor.rb like this:
Ckeditor.setup do |config|
...
config.picture_model { Ckeditor::EditorPicture }
...
end
remove autogenerated defined model from models/ckeditor/picture.rb and add new model /ckeditor/editor_picture.rb
insert to editor_picture.rb
class Ckeditor::EditorPicture < Ckeditor::Asset
mount_uploader :data, CkeditorPictureUploader, :mount_on => :data_file_name
def url_content
url(:content)
end
end

Resources