New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
different embed schemas for the same model (possible pull request) #1001
Comments
You are describing a solution. Can you please describe which problem you are trying to solve? Why do you need different data that looks exactly the same in Elixir? At first, allowing models to become a different struct after load does not sound like a good idea and can potentially be quite confusing. |
@josevalim agreed, would be cool if I could just override use case: request and result are :map, in the db they are postgresql jsonb columns. I want to take advantage of Ecto's type casting, changeset features on the data in the :map fields, because each product_id is going to have the same request/result schema. In my rails app I use STI and have a getter on each class for the request/response attributes. Something like: class SearchReq < ActiveRecord::Base
end
class SearchReq::CRCT < SearchReq
class Request
# some attribs
end
def request
@request ||= Request.new(super)
end
end
class SearchReq::CRST < SearchReq
class Request
# some other attribs
end
def request
@request ||= Request.new(super)
end
end Ecto embeds is very cool, but in it's current form it's very limited to only modeling the same data in each field, where I see a huge benefit is being able to put varying types of data in the same table. A good example of this is a items table in an ecommerce system. Each item may have a price, inventory count, shipping weight, etc. But a clothing item will need attributes such as color, sizes, etc while a computer item will have CPU, RAM, HDD, etc. So it would be real neat to do something like: defmodule Order do
use Ecto.Model
schema "orders" do
embeds_many :items, Item.Clothing, Item.Computer
end
end
defmodule Item.Clothing do
use Ecto.model
embedded_schema do
field :color
end
end
defmodule Item.Computer do
use Ecto.model
embedded_schema do
field :cpu
end
end Back to me SearchReq model, one idea I'm throwing around is have a SearchReq.to_product_searchreq fn that will return SearchReq.CRCT, SearchReq.CRST etc. Maybe even store it in a virtual field. Thanks, Troy |
Ok, that makes a bit more sense. However I am thinking that, if you want to store anything in the field, then you don't want an embed but keep it as a map (or array of maps) and manage your own structs. The reason here is that Ecto does not store model information in embed so we wouldn't know which model to serialize it back too. Luckily, if you drop Ecto in favor of a map, you can easily make it whatever you want. You can even use a custom type that does all the encoding/decoding for you. |
I have the following schema:
I want to use different embed schema's based on the value of
product_id
and embed them in the request and result :map fields. At first, I thought theafter_load
callback would work because I could do a cond on the product_id and return a different model. But I get this error:If there is not a good way to do this, any interest in a pull-request to make after_load not require the same model to be returned? There does not appear to be any code after the
Schema.__load__/6
that depends on the same model being and while I understand the other callbacks require a changeset to be returned, is there really a reason to ensure after_load keeps the same model?The text was updated successfully, but these errors were encountered: