Help
RSS
API
Feed
Maltego
Contact
Domain > forbes.dev
×
Welcome!
Right click nodes and scroll the mouse to navigate the graph.
×
More information on this domain is in
AlienVault OTX
Is this malicious?
Yes
No
DNS Resolutions
Date
IP Address
2019-05-22
206.189.73.52
(
ClassC
)
2021-10-03
184.72.19.87
(
ClassC
)
2024-07-04
50.18.142.31
(
ClassC
)
Port 443
HTTP/1.1 200 OKAccept-Ranges: bytesAge: 0Cache-Control: public,max-age0,must-revalidateCache-Status: Netlify Edge; fwdmissContent-Length: 17874Content-Type: text/html; charsetUTF-8Date: Thu, 04 Jul 2024 21:10:34 GMTEtag: f0fe29492c4a5a9aa120f86597b92d58-sslServer: NetlifyStrict-Transport-Security: max-age31536000X-Nf-Request-Id: 01J1ZSBBVS5NV904W11V5KKAT0 !doctype html>html> head> meta charsetutf-8> meta http-equivx-ua-compatible contentieedge> meta nameviewport contentwidthdevice-width, initial-scale1, shrink-to-fitno> !-- Use the title from a pages frontmatter if it has one --> title>Middleman/title> link href/stylesheets/site.css relstylesheet /> link href/stylesheets/highlighting.css relstylesheet /> script src/javascripts/site.js>/script> /head> body> h2>a href/2017/07/14/using-model-factory-states-to-create-related-models/>Using Model Factory States To Create Related Models/a> span>Jul 14/span>/h2> !-- use article.summary(250) if you have Nokogiri available to show just the first 250 characters --> p>em>strong>Update 2019:/strong> my opinions on this topic have changed quite a bit since it was originally published. See the update section at the bottom of this article/em>/p>p>Laravel’s model factories can be used to automatically create related models when the factory is called. This is a great way to DRY up the arrange portion of your tests. Consider the following factory definition:/p>div classhighlight>pre classhighlight php>code>span classnv>$factory/span>span classo>->/span>span classna>define/span>span classp>(/span>span classnx>Comment/span>span classo>::/span>span classna>class/span>span classp>,/span> span classk>function/span> span classp>(/span>span classnv>$faker/span>span classp>)/span> span classp>{/span> span classk>return/span> span classp>/span> span classs1>post_id/span> span classo>>/span> span classnx>factory/span>span classp>(/span>span classnx>Post/span>span classo>::/span>span classna>class/span>span classp>)/span>span classo>->/span>span classna>lazy/span>span classp>(),/span> span classs1>content/span> span classo>>/span> span classnv>$faker/span>span classo>->/span>span classna>sentence/span>span classp>()/span> span classp>;/span>span classp>});/span>/code>/pre>/div>p>This factory will create a comment along with a post whenever it is called unless the post is explicitly provided./p>div classhighlight>pre classhighlight php>code>span classc1>// creates a comment and a post/span>span classnx>factory/span>span classp>(/span>span classnx>Comment/span>span classo>::/span>span classna>class/span>span classp>)/span>span classo>->/span>span classna>create/span>span classp>();/span>span classc1>// uses the provided post instead of creating one/span>span classnv>$post/span> span classo>/span> span classnx>factory/span>span classp>(/span>span classnx>Post/span>span classo>::/span>span classna>class/span>span classp>)/span>span classo>->/span>span classna>create/span>span classp>();/span>span classnv>$comment/span> span classo>/span> span classnx>factory/span>span classp>(/span>span classnx>Comment/span>span classo>::/span>span classna>class/span>span classp>)/span>span classo>->/span>span classna>create/span>span classp>(/span> span classs1>post_id/span> span classo>>/span> span classnv>$post/span>span classo>->/span>span classna>id/span>span classp>);/span>/code>/pre>/div>p>While the first example can save you from having to repeat the post creation call across your test suite, I think it suffers from two problems. First, when a comment is created with code>$comment factory(Comment::class)->create();/code> I cannot tell just by looking at the test that a post has also been created. This implicit behavior could confuse my future self or anyone else working with the code. Second, I will no longer be able to use the factory as an argument to the save() method:/p>div classhighlight>pre classhighlight php>code>span classnv>$post/span>span classo>->/span>span classna>comments/span>span classp>()/span>span classo>->/span>span classna>save/span>span classp>(/span>span classnx>factory/span>span classp>(/span>span classnx>Comment/span>span classo>::/span>span classna>class/span>span classp>)/span>span classo>->/span>span classna>make/span>span classp>());/span>/code>/pre>/div>p>This code will correctly assign the comment to the post, as expected. However, since the post_id is not explicitly provided to the comment factory an additional unassigned post will be created./p>p>Despite its convenience I think these two problems limit the usefulness of the lazy() method. Fortunately Laravel gives us a solution - model factory states:/p>div classhighlight>pre classhighlight php>code>span classnv>$factory/span>span classo>->/span>span classna>define/span>span classp>(/span>span classnx>Comment/span>span classo>::/span>span classna>class/span>span classp>,/span> span classk>function/span> span classp>(/span>span classnv>$faker/span>span classp>)/span> span classp>{/span> span classk>return/span> span classp>/span> span classs1>content/span> span classo>>/span> span classnv>$faker/span>span classo>->/span>span classna>sentence/span>span classp>()/span> span classp>;/span>span classp>});/span>span classnv>$factory/span>span classo>->/span>span classna>state/span>span classp>(/span>span classnx>Comment/span>span classo>::/span>span classna>class/span>span classp>,/span> span classs1>withPost/span>span classp>,/span> span classk>function/span> span classp>(/span>span classnv>$faker/span>span classp>)/span> span classp>{/span> span classk>return/span> span classp>/span> span classs1>post_id/span> span classo>>/span> span classnx>factory/span>span classp>(/span>span classnx>Post/span>span classo>::/span>span classna>class/span>span classp>)/span>span classo>->/span>span classna>lazy/span>span classp>(),/span> span classp>;/span>span classp>});/span>/code>/pre>/div>p>By defining a state we can use the base comment factory as an argument to the save() method without an additional post being created. When we need a comment with a post we can be explicit and use the code>withPost/code> state./p>div classhighlight>pre classhighlight php>code>span classc1>// No unassigned post since the base comment factory does not define it/span>span classnv>$post/span>span classo>->/span>span classna>comments/span>span classp>()/span>span classo>->/span>span classna>save/span>span classp>(/span>span classnx>factory/span>span classp>(/span>span classnx>Comment/span>span classo>::/span>span classna>class/span>span classp>)/span>span classo>->/span>span classna>make/span>span classp>());/span>span classc1>// Creates the post but is explicit about it/span>span classnv>$comment/span> span classo>/span> span classnx>factory/span>span classp>(/span>span classnx>Comment/span>span classo>::/span>span classna>class/span>span classp>)/span>span classo>->/span>span classna>states/span>span classp>(/span>span classs1>withPost/span>span classp>)/span>span classo>->/span>span classna>create/span>span classp>();/span>/code>/pre>/div>h4 idupdate-2019>Update 2019/h4>p>I now disagree with much of what is written above. A model factory should include everything that is required to create a valid model (but nothing more). If a post is required to create a comment then that definitely belongs in the comment factory. Otherwise every time we use that factory in our tests we are going to have to deal with assigning the post. The original article listed two problems:/p>blockquote> p>When a comment is created with code>$comment factory(Comment::class)->create();/code> I cannot tell just by looking at the test that a post has also been created./p>/blockquote>p>This is a good thing. If the post is not needed by the test then I dont want to see it. Having details about the post in a test that is only testing the comment is noise that obscures the meaning of the test./p>blockquote> p>I will no longer be able to use the factory as an argument to the save() method … code>$post->comments()->save(factory(Comment::class)->make());/code> … since the post_id is not explicitly provided to the comment factory an additional unassigned post will be created./p>/blockquote>p>I do like the simplicity of passing the factory to the save method but I no longer believe its worth the tradeoffs. The alternative is not significantly worse:/p>div classhighlight>pre classhighlight php>code>span classnv>$post/span> span classo>/span> span classnx>factory/span>span classp>(/span>span classnx>Post/span>span classo>::/span>span classna>class/span>span classp>)/span>span classo>->/span>span classna>create/span>span classp>();/span>span classnv>$comment/span> span classo>/span> span classnx>factory/span>span classp>(/span>span classnx>Comment/span>span classo>::/span>span classna>class/span>span classp>)/span>span classo>->/span>span classna>create/span>span classp>(/span> span classs1>post_id/span> span classo>>/span> span classnv>$post/span>span classo>->/span>span classna>id/span>span classp>);/span>/code>/pre>/div>p>And its fine because we are only going to do this when the test actually needs both the post and a comment. Our test setup code is inline with what is to come in the test./p>p>I still use model factory states frequently, but when it comes to creating relationships with them I recommend them in situations where the related model is not a required field. A potential use case could be the other side of this comment -> post relationship:/p>div classhighlight>pre classhighlight php>code>span classnv>$post/span> span classo>/span> span classnx>factory/span>span classp>(/span>span classnx>Post/span>span classo>::/span>span classna>class/span>span classp>)/span>span classo>->/span>span classna>states/span>span classp>(/span>span classs1>withComments/span>span classp>)/span>span classo>->/span>span classna>create/span>span classp>();/span>/code>/pre>/div>p>This communicates that our test needs a post with some comments but the details of these comments are not going to be important./p> h2>a href/2017/05/01/persisting-polymorphism/>Persisting Polymorphism/a> span>May 1/span>/h2> !-- use article.summary(250) if you have Nokogiri available to show just the first 250 characters --> p>Recently I worked on a project where a users choice needed to permanently modify the behavior of an object. The gist of the project is that a user is creating a job posting and at some point they will choose how they wish to publish the job: using a job credit, as a daily rate, on a recruiting plan, etc. The choice of publishable type alters the behavior of the job every time the user decides to change its status (from draft to open, draft to scheduled, open to closed). For example: when a job credit job is changed from draft status to open status the system has to verify that a credit is available and then use the credit on the job, but a daily rate job would instead charge the users credit card./p>p>You can imagine how this could lead to some pretty nasty code:/p>div classhighlight>pre classhighlight php>code>span classk>public/span> span classk>function/span> span classnf>open/span>span classp>()/span>span classp>{/span> span classk>if/span> span classp>(/span>span classnv>$this/span>span classo>->/span>span classna>publishable_type/span> span classo>/span> span classs1>credit/span>span classp>)/span> span classp>{/span> span classc1>// verify credit is available and anything else that/span> span classc1>// needs to be done before a credit job is opened/span> span classp>}/span> span classk>elseif/span> span classp>(/span>span classnv>$this/span>span classo>->/span>span classna>publishable_type/span> span classo>/span> span classs1>daily/span>span classp>)/span> span classp>{/span> span classc1>// charge credit card or anything that needs to be/span> span classc1>// done before a daily job is opened/span> span classp>}/span> span classk>elseif/span> span classp>(/span>span classnv>$this/span>span classo>->/span>span classna>publishable_type/span> span classo>/span> span classs1>plan/span> span classp>{/span> span classc1>// an elseif for any other types/span> span classp>}/span> span classnv>$this/span>span classo>->/span>span classna>status/span> span classo>/span> span classs1>open/span>span classp>;/span> span classnv>$this/span>span classo>->/span>span classna>save/span>span classp>();/span> span classc1>// and any other code that has to be executed when a job is/span> span classc1>// opened regardless of which publishable type is chosen/span> span classk>if/span> span classp>(/span>span classnv>$this/span>span classo>->/span>span classna>publishable_type/span> span classo>/span> span classs1>credit/span>span classp>)/span> span classp>{/span> span classc1>// assign credit to job/span> span classp>}/span> span classk>elseif/span> span classp>(/span>span classnv>$this/span>span classo>->/span>span classna>publishable_type/span> span classo>/span> span classs1>daily/span>span classp>)/span> span classp>{/span> span classc1>// whatever needs to be done for daily job/span> span classp>}/span> span classk>elseif/span> span classp>(/span>span classnv>$this/span>span classo>->/span>span classna>publishable_type/span> span classo>/span> span classs1>plan/span> span classp>{/span> span classc1>// an elseif for any other types/span> span classp>}/span>span classp>}/span>/code>/pre>/div>p>This implementation would result in the code>open()/code> method being modified anytime a new publishable type is added. Similar methods would have to exist for the other job status changes as well. Not a maintainable approach. If we could abstract the behavior for each of the types into their own classes this method could be significantly improved. Consider if the open method could look like this instead:/p>div classhighlight>pre classhighlight php>code>span classk>public/span> span classk>function/span> span classnf>open/span>span classp>()/span>span classp>{/span> span classnv>$this/span>span classo>->/span>span classna>publishableType/span>span classp>()/span>span classo>->/span>span classna>beforeOpen/span>span classp>();/span> span classnv>$this/span>span classo>->/span>span classna>status/span> span classo>/span> span classs1>open/span>span classp>;/span> span classnv>$this/span>span classo>->/span>span classna>save/span>span classp>();/span> span classnv>$this/span>span classo>->/span>span classna>publishableType/span>span classp>()/span>span classo>->/span>span classna>afterOpen/span>span classp>();/span>span classp>}/span>/code>/pre>/div>p>Much nicer./p>p>To make this work the code>publishableType()/code> method needs to return a new instance of the type class. We can take a cue from Laravel’s polymorphic relationships and save the namespace of the type class to a code>publishable_type/code> column on the job table. Meaning that the column would contain something along the lines of: code>App\Daily/code>, code>App\Credit/code> or code>App\Whatever/code>. The code>publishableType()/code> implementation looks like:/p>div classhighlight>pre classhighlight php>code>span classk>public/span> span classk>function/span> span classnf>publishableType/span>span classp>()/span>span classp>{/span> span classk>return/span> span classk>new/span> span classnv>$this/span>span classo>->/span>span classna>publishable_type/span>span classp>(/span>span classnv>$this/span>span classp>);/span>span classp>}/span>/code>/pre>/div>p>And that is it. As long as each publishable type implements the same interface then changing the behavior of a job is a simple as persisting a different publishable type to the database./p> /body>/html>
View on OTX
|
View on ThreatMiner
Please enable JavaScript to view the
comments powered by Disqus.
Data with thanks to
AlienVault OTX
,
VirusTotal
,
Malwr
and
others
. [
Sitemap
]