Comments (12)
I'll have to look into this more. Under the hood ExMachina uses changesets, so it might not be hard to also cast all the fields. I'm not totally sure ExMachina should handle this, but I'll think about it.
from ex_machina.
Thank you :) I think dates/times in factories might be a bit painful otherwise – though maybe there's a nicer way than what I did.
from ex_machina.
In the meantime you could simplify this by extracting a private function and calling Ecto.DateTime.cast
def factory(:package, _attrs) do
%Package{
hex_update_at: date_time("2001-02-03T04:05:06Z")
}
end
defp date_time(date_time) do
Ecto.DateTime.cast(date_time)
end
from ex_machina.
@paulcsmith Good idea, thank you.
I'll sneak this in here since it's quite related: I'm unable to get this working for passed-in dates.
I tried this:
def factory(:package, attrs) do
time = Dict.get(attrs, :hex_updated_at, "2001-02-03T04:05:06Z")
{:ok, cast_time} = Ecto.DateTime.cast(time)
%Package{
name: sequence(:name, &"package#{&1}"),
description: "A package.",
hex_updated_at: cast_time,
}
end
The default value is cast OK, but if I pass in a custom value, it is not cast. I debugged a bit and it seems the changes
changeset that ExMachina.Ecto.save_record/3
gets does indeed not have the cast value. I guess I'm misunderstanding something about how you're meant to customize attributes if you also want to massage them a bit.
from ex_machina.
@henrik Ah yes, that is a good point. The problem is that the cast attribute is overridden because the attrs
are merged in after the factory/2
function is called. You can do what I said with a hard-coded binary, but if it's from the attrs
it won't work unless you custom the save_record
function to cast the changes with Ecto.Changeset.cast.
The more I think about it, the more it seems like this should be part of ExMachina.Ecto. I'll probably add it this week or next. Unless you want to try to tackle it in a PR :) I think it just needs to get the changes and pass them through Ecto.Changeset.cast.
from ex_machina.
Oh yeah, I just found that part of the code. This bit, right?
def build(module, factory_name, attrs \\ %{}) do
attrs = Enum.into(attrs, %{})
module.factory(factory_name, attrs) |> Map.merge(attrs)
end
from ex_machina.
I would love to tackle it in a PR, but I'm hard-pressed to find time for the project I'm actually trying to work on, so I don't think I'll have the time to spare until that's done :/ I'll customize save_record
for now – good idea.
from ex_machina.
No problem, I totally understand. Yes that's the bit that merges the parameters and overrides your cast one. Good luck with your project :)
from ex_machina.
I started work on this, but it relies on elixir-ecto/ecto#1081 before I can get it working with associations. Once a new version of Ecto is released I can pick this work up again
from ex_machina.
I'm going to check this when Ecto 2.0 comes out to see if it is handled automatically when you call Repo.insert!
. That would be the most ideal solution, but if that doesn't work I'll try to come up with something else. I do agree that automatically casting would be a lot nicer. That way you can give it an erlang time from GoodTimes (as an example) and it would cast it correctly without having to do explicit conversion every time
from ex_machina.
Chatted with @josevalim about this on IRC
[11:42:03] <paulcsmith_> josevalim Hmm, any ideas on how to handle this? #54 basically, it would be nice if you could set a datetime with an erlang datetime, but you have to manually cast it somewhere, either in the factory or when setting the attrs
[11:42:19] <paulcsmith_> And if you don't have time, no worries :)
[11:43:40] <paulcsmith_> Maybe I could cast everything and then call apply_changes before passing the record to Repo.insert. That's the first thing that comes to mind that might work. Not sure of the ramifications though
[11:44:31] paulcsmith_: i would say you should pass the proper value in
[11:44:45] paulcsmith_: datetime(....) when you call the factory
[11:44:49] paulcsmith_: won't hurt
[11:45:03] build(:package, inserted_at: datetime("...."))
[11:45:07] can even make it a sigil
[11:45:09] ~d(...)
[11:45:12] <paulcsmith_> Yeah that might be the best option. It's what I'm doing now and it does work :)
[11:45:24] <paulcsmith_> Oh the sigil idea sounds interesting. I'll have to try that out.
[11:45:27] <paulcsmith_> Thanks for the input :)
To sum up, the best option might be to add the datetime
function as mentioned here to your factory, or add a sigil that does that for you. You'd probably want to make it a public function though so it could be used in your tests to override attributes: build(:package, inserted_at: datetime(GoodTimes.a_day_ago))
I'm considering adding a sigil to ExMachina.Ecto that you could optionally import, but it might be simple enough to just do on your own and we could add it to the README instead.
Does this help @henrik?
from ex_machina.
I'm going to close this in favor of #94. Let me know if you have any further feedback on the other issue please :)
from ex_machina.
Related Issues (20)
- def build/2 defines defaults multiple times HOT 2
- Use of `build( ... )` with Ecto 3.4+ leads to many association preload warnings HOT 7
- Compiler warning when using an a project using Elixir 1.11 HOT 3
- Insert with assocs fails constraint HOT 1
- Proposal: Introduce build_lazy/2 HOT 3
- Test-only implementation fails HOT 4
- Cast polymorphic embeds HOT 8
- Inserted data breaks manual test HOT 3
- Allow sequence in attributes passed to `insert_list` HOT 5
- Hundreds of depreciation compiler warnings when running tests HOT 4
- insert/2 doesn't work with compound primary keys HOT 3
- Allow sequences indices to be persisted between runs HOT 2
- sequence starting with 0
- Is this project maintained? HOT 17
- Sequence reset doesn't respect the `start_at` option
- sequence(:example_id, & &1) put chars instead of integer HOT 3
- Stringify `Ecto.Enum` values when using `string_params`/`string_params_with_assocs`
- Option to have `insert_list` leverage Ecto's `insert_all`
- an intermittent error on async false tests HOT 1
- nvim diagnostics error HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ex_machina.