How to configure searchkick with multiple elastic search servers? - ruby-on-rails

I want to set up a different server per model for searchkick.
For example:
# config/initializers/elasticsearch.rb
Elasticsearch::Model.client = Elasticsearch::Client.new(hosts: elasticSearchConfig)
Searchkick.client = Elasticsearch::Model.client
# This model uses a client pointing to a specific elastic server.
class ModelA < ApplicationRecord
searchkick
end
# This model uses a client pointing to another specific elastic server.
class ModelB < ApplicationRecord
searchkick
end

Related

Rails - active storage and multi databases

Is is possible to use active storage with multi databases in rails? I have the following models:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
end
class OtherRecord < ActiveRecord::Base
self.abstract_class = true
connects_to database: { writing: :other_db }
end
class SomeModel < OtherRecord
has_many_attached :files
end
I've added active storage migrations scoped to the secondary database and necessary tables were created there but ActiveStorage seems to look for tables in primary database. Have anyone a solution for that?

Rails builds invalid sql query for has many association

I have a models like below
# Base model
class RecordBase < ActiveRecord::Base
self.table_name = 'records'
has_many :record_images, as: assetable, dependent: :destroy
fileuploads :record_images
end
# Inherited model
class SpecificRecord < RecordBase
end
# Image model
class RecordImage < ActiveRecord::Base
include Uploader::Asset
belongs_to :assetable, polymorphic: true
end
I'm using https://github.com/superp/rails-uploader for upload files. I have record of RecordImage model in database with assetable_id corresponding to SpecificRecord record and assetable_type 'SpecificRecord' but when I try SpecificRecord.find(some_id).record_images in console, rails builds sql query with assetable_type 'RecordBase' and hence finds nothing. How to specify which assetable_type should be in sql query?
Update
That's issue about rails-uploader gem, in version '0.2.8' gem redefined .base_class and saves data to db with assetable_type of child class, but in version '0.4.5' assets saves to db with assetable_type of base class.

Rails share custom database connection between classes - without class inheritance?

I have a replica database slave running, where I want to send some readonly calls to, to offload the master. For this reason I would like to create two customs models, that connect separately to that database, so that I can use those, whenever I have the need to offload some queries.
I have two classes:
class Car < ActiveRecord::Base
has_many :prices
end
class Price < ActiveRecord::Base
belongs_to :car
end
Rails has the possibility to share custom database connections on model level like this:
class MyCustomDbConnection < ActiveRecord::Base
self.abstract_class = true
establish_connection({database: 'www.slavedb.com', port: 5432, pass: 'some'})
end
class ReadonlyCar < MyCustomDbConnection
end
class ReadonlyPrice < MyCustomDbConnection
end
While this works well, my use case is that I would ALSO like to have the ´ReadonlyCar´ and ReadonlyPrice inherit from the original models that uses the default ActiveRecord::Base.connection. This is needed to have the ReadonlyCar behave exactly like the original one Car (business logic). Now I can't do class inheritance from both ReadonlyCar < MyCustomDbConnection and ReadonlyCar < Carat the same time, so how do I get the full functionality from Car, but share the same connection to the slave between both ReadonlyCar and ReadonlyPrice?
You could write a module where in the included hook you do that call to establish the connection.
module MyCustomDbConnection
def self.included(base)
base.establish_connection(
database: 'www.slavedb.com',
port: 5432,
pass: 'some'
)
end
end
class ReadOnlyCar < Car
include MyCustomDbConnection
end

Single Table Inheritance & ActiveRecord Associations

I'm attempting to have a parent model that other models inherit from, and a secondary class that has associations with the children from the first model. Here's what I have so far...
I used the first command to create the parent model.
rails g model Person name:string age:integer height:float
I then set up Person as the parent class, and two children class which inherit from it as seen below.
class Person < ActiveRecord::Base
self.abstract_class = true
end
class Driver < Person
self.table_name = "Driver"
belongs_to :vehicle
end
class Passenger < Person
self.table_name = "Passenger"
belongs_to :vehicle
end
I also set up a Vehicle class to use in an association with the Driver and Passenger children classes.
rails g model Vehicle color:string capacity:integer
class Vehicle < ActiveRecord::Base
has_one :driver
has_many :passengers
end
However, if I use the rails console and attempt to create a new instance Driver or Passenger, using Driver.new or Passenger.new, I encounter an PostgreSQL error.
For reasons which I cannot figure out, Rails is writing SQL statements to query on a Driver or Passenger table. However, it is my understanding that only one Person table is made and has a type attribute that is used for queries.
If anyone can offer some guidance here, I'd be very appreciative.
Thanks
Since it seems you're trying to use the common table persons for both Driver and Passenger, you don't need the abstract_class declaration, or the table_name declarations in either of the sub classes. Per the rails documentation, these options would be used when you want classes to inherit behavior from their parent, without the parent itself having a table.
The snippet below should work fine.
class Person < ActiveRecord::Base
end
class Driver < Person
belongs_to :vehicle
end
class Passenger < Person
belongs_to :vehicle
end

Stop nesting data of the active model serializer gem

I am using the active model serializer gem, and it works fine for now. I have however stumbled upon an issue, where I wan't to stop the nesting of the data retrieved.
Lets say I have 3 models:
Users who has_many orders who has_many addresses.
Normally in my Users serializer class I would have have a has_many to the orders model, and in the orders model serializer have a has_many relationship to the addresses.
I now have a users controller, where I don't want the orders out, but not the nested addresses. Can this be done without creating a whole new serializer class?
Update, to clarify:
I have the following 3 models:
class User < ActiveRecord::Base
has_many orders
end
class Orders < ActiveRecord::Base
belongs_to user
has_many addresses
end
class Addresses < ActiveRecord::Base
belongs_to order
end
I have 3 serializers which are identical to the models.
For my orders API I would like to retrieve the addresses as well, but when I query users I only wants the associated orders and not addresses. As it is now when I query the users it both returns all the orders and addresses, since I have a has_many to addresses from the orders.
Is the only option to create separate serializers for the two options (it just doesn't feel very DRY)?
You can use default_serializer_options method that defines serializer options for
all serializers and their children used by this controller.
#users_controller.rb
class UsersController < ApplicationController
def default_serializer_options
{ include_addresses: false }
end
end
Then override initialize method in Order serializers to check serializer options for include_addresses flag:
# order_serializer.rb
class OrderSerializer < ActiveModel::Serializer
def initialize(object, options = {})
options.reverse_merge! include_addresses: true # by default it should include addresses
#include_addresses = options[:include_addresses]
super
end
def include_addresses?
#include_addresses
end
end
And that's it. Specify this option in every controller that you don't need addresses to be nested.
You can remove the has_many from the serializer and it will stop including the associations.

Resources