<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Paul-Armand Assus on Medium]]></title>
        <description><![CDATA[Stories by Paul-Armand Assus on Medium]]></description>
        <link>https://medium.com/@poilon?source=rss-5800db19dc30------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/0*xLc8mj819urvHYvm.jpg</url>
            <title>Stories by Paul-Armand Assus on Medium</title>
            <link>https://medium.com/@poilon?source=rss-5800db19dc30------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 16:17:08 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@poilon/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Domain Driven Design with GraphQL on Ruby on Rails API]]></title>
            <link>https://medium.com/@poilon/domain-driven-design-with-graphql-on-ruby-on-rails-api-3f0f2a090b4f?source=rss-5800db19dc30------2</link>
            <guid isPermaLink="false">https://medium.com/p/3f0f2a090b4f</guid>
            <category><![CDATA[freelancing]]></category>
            <category><![CDATA[graphql]]></category>
            <category><![CDATA[ruby-on-rails]]></category>
            <category><![CDATA[ruby]]></category>
            <category><![CDATA[domain-driven-design]]></category>
            <dc:creator><![CDATA[Paul-Armand Assus]]></dc:creator>
            <pubDate>Wed, 14 Feb 2018 14:17:57 GMT</pubDate>
            <atom:updated>2018-03-12T10:44:24.595Z</atom:updated>
            <content:encoded><![CDATA[<p>Hello everyone,</p><p>For the past year, at <a href="https://www.aline.work/"><strong><em>A line</em></strong></a>, we had to build an ambitious project management and marketplace platform MVP from scratch. The frontend is built in TypeScript/React/Apollo (<a href="https://medium.com/u/15f3248b44fe">Charly Poly</a>).</p><p>For the backend, Charly and I had three goals :</p><ul><li>Implementing <strong>DDD</strong> in Rails</li><li>Implementing a <strong>GraphQL</strong> API with <strong>WebSocket</strong> subscriptions</li><li>Having a <strong>well-tested</strong>, <strong>maintainable</strong>, and <strong>scalable</strong> codebase</li></ul><p>FYI, today it’s all up and running in production on <a href="https://www.aline.work/"><strong><em>A Line</em></strong></a>, the Startup I work on.</p><h3>The gems</h3><p>Basic rails/puma/pg/sidekiq/redis. For authentication we choose to use a very pleasant API called Auth0, that provide JWT authentication. For search we use Algolia. Of course, for graphql, the graphql-ruby gem.</p><h3>The core Architecture</h3><p>Let’s get an example with the model Portfolio. I’ll not go into subscriptions, but it works great with ActionCable (next article ?).</p><pre><strong>app/</strong><br><strong>app/admin/</strong>                      # ActiveAdmin<br><strong>app/models/</strong>                     # The models (User/Portfolio ....)<br><strong>app/controllers/</strong>                # Only for the GraphQL controller<br><strong>app/graphql/</strong>                    # The GraphQL code</pre><pre><strong>app/graphql/aline_api_schema.rb</strong>   # Main graphql schema<br><strong>app/graphql/mutation_type.rb</strong>      # Defines all mutations<br><strong>app/graphql/query_type.rb</strong>         # Defines all queries<br><strong>app/graphql/subscriptions_type.rb</strong> # Defines the subscriptions</pre><pre><strong>app/graphql/resource_base_service.rb</strong><br># Base service object that exposes the index/show/create/update/destroy basic methods that will be called by the mutations</pre><pre><strong>app/graphql/portfolios/                     </strong># Portfolio domain<strong><br>app/graphql/portfolios/type.rb              </strong># Portfolio GraphQL type<strong><br>app/graphql/portfolios/mutations/<br>app/graphql/portfolios/mutations/create.rb </strong> # Create mutation<strong><br>app/graphql/portfolios/mutations/update.rb </strong> # Update mutation<strong><br>app/graphql/portfolios/mutations/accept.rb </strong> # Accept mutation<strong><br>app/graphql/portfolios/mutations/input_type.rb </strong> # Portfolio input</pre><pre><strong>app/graphql/portfolios/service.rb</strong><br># Service Object that may surcharge the index/show/create... methods inherited by resource_base_service methods called by the mutations, and add the accept method.</pre><h3>The code</h3><h3>The controller</h3><p>The GraphQL controller is pretty simple, just calling the graphql schema.</p><pre><strong>app/controllers/graphql_controller.rb</strong></pre><pre>class GraphqlController &lt; ApplicationController</pre><pre>  before_action :authenticate_user</pre><pre>  # GraphQL endpoint<br>  def execute<br>    result = AlineApiSchema.execute(<br>      params[:query],<br>      variables: ensure_hash(params[:variables]),<br>      context: { current_user: current_user },<br>      operation_name: params[:operationName]<br>    )<br>    render json: result<br>  end<br></pre><pre>  private<br></pre><pre>  def ensure_hash(ambiguous_param)<br>    case ambiguous_param<br>    when String<br>      ambiguous_param.present? ? ensure_hash(JSON.parse(ambiguous_param)) : {}<br>    when Hash, ActionController::Parameters<br>      ambiguous_param<br>    when nil<br>      {}<br>    else<br>      raise ArgumentError, &quot;Unexpected parameter: #{ambiguous_param}&quot;<br>    end<br>  end</pre><pre>end</pre><h3>The Service Object part</h3><p>the ResourceBaseService (simplified) looks like that :</p><pre><strong>app/graphql/resource_base_service.rb</strong></pre><pre>class ResourceBaseService</pre><pre>  attr_accessor :params, :object, :user</pre><pre>  def initialize(params: {}, object: nil, object_id: nil, user: nil)<br>    @params = params.to_h.symbolize_keys<br>    @object = object || model.find_by(id: object_id)<br>    @user = user<br>  end</pre><pre>  def self.graphql_call(resource, method)<br>    lambda { |_obj, args, ctx|<br>      params = args.try(:[], resource.to_sym) || args<br>      service = &quot;{resource.to_s.pluralize.camelize}::Service&quot;<br>      service.constantize.new(<br>        params: params,<br>        user: ctx[:current_user],<br>        object_id: args[:id]<br>      ).send(method)<br>    }<br>  end</pre><pre>  def index<br>    # Example of a index if ApplicationRecord defines the<br>    # self.seeable_by method<br>    model.seeable_by(user: user)<br>  end</pre><pre>  def show<br>    # Example of a show if ApplicationRecord defines the<br>    # self.seeable_by method<br>    return not_allowed unless model.seeable_by(user: user).include?(object)<br>    object<br>  end</pre><pre>  def create<br>    # Creates the record regarding params and authorizations<br>    model.create!(params)<br>  end</pre><pre>  def destroy<br>    # Destroys the record regarding authorizations<br>    object.destroy!<br>  end</pre><pre>  def update<br>    # Updates the record regarding params and authorizations<br>    object.update_attributes!(params)<br>  end</pre><pre>  private<br>  <br>  def singular_resource<br>    resource_name.singularize<br>  end</pre><pre>  def model<br>    singular_resource.camelize.constantize<br>  end</pre><pre>  def resource_name<br>   self.class.to_s.split(&#39;:&#39;).first.underscore<br>  end</pre><pre>end</pre><p>Then you have the Portfolios Service</p><pre><strong>app/graphql/portfolios/service.rb</strong></pre><pre>module Portfolios<br>  class Service &lt; ResourceBaseService</pre><pre>    # Custom Mutation<br>    def accept<br>      return unless model.writable_by(user: user).include?(object)<br>      object.tap(&amp;:accept!)<br>    end</pre><pre>    # Add action after create<br>    def create<br>      super<br>      # add fancy stuff<br>    end</pre><pre>    # Rewritten index<br>    def index<br>      model.where(visible: true).seeable_by(user: user)<br>    end</pre><pre>  end<br>end</pre><h3>The GraphQL part</h3><p>The Portfolio Type</p><pre><strong>app/graphql/portfolios/type.rb</strong></pre><pre>Portfolios::Type = GraphQL::ObjectType.define do<br>  name &#39;Portfolio&#39;</pre><pre>  field :id, types.ID # types.String for uuid mapping<br>  field :visible, types.Bool<br>  field :user_id, types.ID<br>  field :created_at, types.String<br>  field :updated_at, types.String<br>end</pre><p>And the mutations, first the input type, you can have many :</p><pre><strong>app/graphql/portfolios/mutations/input_type.rb</strong></pre><pre>Portfolios::Mutations::InputType = GraphQL::InputObjectType.define do</pre><pre>  name &#39;Portfolio input type&#39;</pre><pre>  argument :visible, types.Bool<br>  argument :user_id, types.ID</pre><pre>end</pre><p>and for example the update mutation :</p><pre><strong>app/graphql/portfolios/mutations/update.rb</strong></pre><pre>Portfolios::Mutations::Update = GraphQL::Field.define do</pre><pre>  description &#39;Updates a Portfolio&#39;</pre><pre>  type Portfolios::Type<br>  argument :id, !types.ID<br>  argument :portfolio, Portfolios::Mutations::InputType # The input type defined earlier<br>  resolve ResourceBaseService.graphql_call(:portfolio, :update)<br>end</pre><p>Then simply add them to the mutations_type :</p><pre><strong>app/graphql/mutation_type.rb</strong></pre><pre>MutationType = GraphQL::ObjectType.define do</pre><pre>  name &#39;Mutation&#39;</pre><pre>  field :update_portfolio, Portfolios::Mutations::Update<br>  # ...<br>end</pre><p>And add the queries to the query_type :</p><pre><strong>app/graphql/query_type.rb</strong></pre><pre>QueryType = GraphQL::ObjectType.define do</pre><pre>  field :portfolio do<br>    type !Portfolios::Type<br>    description &#39;Return a Portfolio&#39;<br>    argument :id, !types.ID<br>    resolve ResourceBaseService.graphql_call(:portfolios, :show)<br>  end</pre><pre>  field :portfolios do<br>    type !types[!Portfolios::Type]<br>    description &#39;Return the Portfolios&#39;<br>    resolve ResourceBaseService.graphql_call(:portfolios, :index)<br>  end</pre><pre>  # ... Metaprog could be your friend here.</pre><pre>end</pre><p>finally the graphql schema</p><pre><strong>app/graphql/aline_api_schema.rb</strong></pre><pre>AlineApiSchema = GraphQL::Schema.define do<br>  mutation(MutationType)<br>  query(QueryType)<br>  use GraphQL::Subscriptions::ActionCableSubscriptions<br>  subscription(SubscriptionType)<br>end</pre><p>OMG, that’s it, you have your graphql API. So fu**ing good.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/600/1*RGs3RBMbKbfgmIZUOi38kw.jpeg" /></figure><h3>Conclusion</h3><p>The Service Objects part is maybe not the best thing for all projects, but here it works pretty well.</p><p>You can unit test all your services methods, and for me that’s the only real things to test.</p><p>For N+1 queries, I suggest you to tweak your index methods with model.includes() regarding the context ast nodes, or take a look tographql-batch, another wonderful gem made by Shopify ❤.</p><p>The performances are quite good for the moment. GraphQL is a wonderful tool to build APIs, and in ruby it’s pretty pleasant right now :)</p><p>Hope it helps, don’t hesitate to reach me for more details. By the way, if you are a talented freelance and look for quality projects, take a look at <a href="http://www.aline.work/">A line</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=3f0f2a090b4f" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Speedrunning code, the 3 things I re-learnt while recoding a basic ls in C]]></title>
            <link>https://medium.com/hackernoon/speedrunning-code-the-3-things-i-re-learnt-while-recoding-a-basic-ls-in-c-d559b0f1a92b?source=rss-5800db19dc30------2</link>
            <guid isPermaLink="false">https://medium.com/p/d559b0f1a92b</guid>
            <category><![CDATA[unix]]></category>
            <category><![CDATA[c-language]]></category>
            <category><![CDATA[students]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Paul-Armand Assus]]></dc:creator>
            <pubDate>Sat, 22 Jul 2017 13:54:00 GMT</pubDate>
            <atom:updated>2017-07-22T17:56:27.008Z</atom:updated>
            <content:encoded><![CDATA[<p>Hello friends,</p><p>today I wanted to look back at a project I had to do as a student, and I struggled a LOT at the time, and found the project very boring.</p><p>Basically, I had to develop ls, with the -l -r -R and -a options, and with only malloc, free, write, stat, ctime, time, getpwuid, getgrgid, readdir, opendir and closedir.</p><p>As always, I wanted to challenge myself again to rewrite some C. At first, I told myself that it would be an easy 2 hours project as an old C developer, but holy ***, it didn’t. It took me around 5 hours to write a code I’m not proud of, with the not-allowed use of sprintf that saved me time. It still need a lot of testing, memory leak finding, and refactoring (it always need :) ).</p><p><a href="https://github.com/Poilon/c_ls">Poilon/c_ls</a></p><p>But yeah, it’s a great basic project. I would suggest anyone that want to learn C development, to learn basic algorithmic and memory handling to try this one.</p><p>There is 3things at least you will learn.</p><h3>1. Handling memory</h3><p>Rewriting code in a language without garbage collector can be a pain in the ass. It’s hard to keep track of ALL allocated memory to free it after. But after a while, it’s really pleasant to do so. You can really go in fond of performance, and allocate just the minimum memory to your needs for the best algorithm.</p><p>GDB is a wonderful tool that will help anyone debugging C code, but it’s slow to debug C in general, so the best way to have a C program working is to really think a lot before coding.</p><h3>2. Data structures</h3><p>In C, with just the basic functions given, you don’t have great strings/arrays/hashes/linked-list functions. It’s wild.</p><p>I started to do all my data structuration with simple string parsing, and then sorting was a pain, so I worked on a linked-list data structure. Pretty straightforward, but add-delete-sort are basic but great to start algorithmics. It’s good to understand what is behind a sort in Ruby for example. You have a better idea of what is performance and what are the different sort you could use.</p><p>You will need to parse strings, transform a string to a integer, transform an integer to a binary strings etc. A lot of manipulation that leads to a LOT of bugs, that will reduce over time of refactoring.</p><p>It’s important to have a big picture in C development, and not rush to the result, because you will not have any result but “Game over, your code has <strong><em>segfault</em></strong>, try again”</p><p>This part is really important for the -R (recursive) option, as if you just print as you see, it’ll be impossible to apply the algorithm to the folder inside the folders :)</p><h3>3. What is ls, and what are access rights in Unix</h3><p>Everyone one that had use an unix terminal in their lives know what ls is, and what it’s used for. But ls has many many options to format data and use it for your scripts.</p><p>for example, the most known ls -l will give you a string that look like</p><blockquote>total 40<br>-rw-r — r — 1 poilon staff 41 22 jul 13:55 Makefile<br>-rwxr-xr-x 1 poilon staff 14248 22 jul 13:58 c_ls</blockquote><p>and while coding it, you’ll have a better idea of how it works. The read-write-execute rights, the number of links, the owners: user and group etc.</p><p>It’ll for sure be useful for the people that just had a bootcamp in development and don’t use a unix-based system every day.</p><p>This project gave me a real satisfaction when I had a ls -alRr working. I took it as a speedrun of a game, and I had the ls -alRr working in 5h and 12m. Now I’m really tired !</p><p>That was really entertaining and pleasant to redo some C, and I’m sure it made me a better developer anyway !</p><p>Hope you liked the read, tell me what you think and if you want me to do maybe a streamed/youtube version of this kind of challenge, or any other format.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/640/1*WLacqxFazv-_frh5vqpltQ.png" /></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=d559b0f1a92b" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/speedrunning-code-the-3-things-i-re-learnt-while-recoding-a-basic-ls-in-c-d559b0f1a92b">Speedrunning code, the 3 things I re-learnt while recoding a basic ls in C</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[How I got banned from CodeWars]]></title>
            <link>https://medium.com/hackernoon/how-i-got-banned-from-codewars-c21ad6ebee1e?source=rss-5800db19dc30------2</link>
            <guid isPermaLink="false">https://medium.com/p/c21ad6ebee1e</guid>
            <category><![CDATA[ruby]]></category>
            <category><![CDATA[interview-questions]]></category>
            <dc:creator><![CDATA[Paul-Armand Assus]]></dc:creator>
            <pubDate>Sat, 01 Jul 2017 20:34:53 GMT</pubDate>
            <atom:updated>2017-07-21T05:09:32.345Z</atom:updated>
            <content:encoded><![CDATA[<p>Hello everyone.</p><p>I’m a former C developer(for 5 years), that fell in love with Ruby and it’s ecosystem 4 years ago. After few months of practicing Ruby, I had quit my old job to become a full-time RoR developer in a great company, doing a lot of website crawling and working on a big rails application.</p><p>After 2 years in that company, I started to do a lot of recruitment, mainly sourcing and tech interviews.</p><p>It’s at that point in life that I discovered CodeWars (<a href="https://www.codewars.com/">https://www.codewars.com</a>), and used it a lot to do my tech interviews. I trained myself often on the website, and resolved a lot of Katas.</p><p>With my colleagues, we wanted to challenge ourselves and the point was to earn the most CodeWars points in the weekend. With two kids it’s pretty hard to find focus-time, but my nights got shorter for a time !</p><p>After resolving ones of the most hard ruby katas with “normal” solutions<em> (Brainfuck interpreter: </em><a href="https://www.codewars.com/kata/my-smallest-code-interpreter-aka-brainf-star-star-k"><em>https://www.codewars.com/kata/my-smallest-code-interpreter-aka-brainf-star-star-k</em></a><em>, the builder of things: </em><a href="https://www.codewars.com/kata/the-builder-of-things"><em>https://www.codewars.com/kata/the-builder-of-things</em></a><em> and so much more…)</em>, and as a competitor in games (Super Smash Bros. Melee mainly), I had to find a way to destroy my friends at our little game :-)</p><p>The third weekend, something hit me. I was trying to understand how the katas are checked for validity and yes, I had found a way to resolve almost any kata with a same and really simple solution.</p><p>A Kata is checked this way: Does my solution is equal to theirs, or do theirs solution is equal to mine.</p><p>At first I tried to resolve it by returning nil in my method, and surcharge the == operator from NilClass this way</p><pre>class NilClass</pre><pre>  def ==(_)<br>    true<br>  end</pre><pre>end</pre><pre>def mymethod<br>end</pre><p>and I hit submit, and “pfiout”, I had resolved the Kata. I told myself “Oh shit, is that cheating ? Oh I don’t really care, that’s a solution, my friends will be blown !”</p><p>I then tried to make it on the biggest Kata of the website, a 1 kyu. The Three way compiler. As before I tried using a surcharge the == method on the Array or Hash classes, and again “pfiout”, I won points.</p><p>At this point, done for done, I told myself to just rekt my colleagues. I made this <a href="https://github.com/Poilon/codewars-hack">https://github.com/Poilon/codewars-hack</a>, that will win codewars points for me.</p><p>I had a lot of fun finding, and then doing this. Made it to top 300 of the CodeWars power-ranking doing nothing. I did beat my friend, and successfully won our contest ! Of course I would love to have my account back, even with 0 points, just to answer comments and see the new solutions on the Kata I submitted myself.</p><p>Of course this is cheating, but if someone had done this during code interviews, I think he would have a really good chance of being hired !</p><p>Ruby is love, ruby is jazz. ❤ Paris.rb !</p><blockquote><a href="http://bit.ly/Hackernoon">Hacker Noon</a> is how hackers start their afternoons. We’re a part of the <a href="http://bit.ly/atAMIatAMI">@AMI</a>family. We are now <a href="http://bit.ly/hackernoonsubmission">accepting submissions</a> and happy to <a href="/service/mailto:partners@amipublications.com">discuss advertising &amp; sponsorship</a> opportunities.</blockquote><blockquote>To learn more, <a href="https://goo.gl/4ofytp">read our about page</a>, <a href="http://bit.ly/HackernoonFB">like/message us on Facebook</a>, or simply, <a href="https://goo.gl/k7XYbx">tweet/DM @HackerNoon.</a></blockquote><blockquote>If you enjoyed this story, we recommend reading our <a href="http://bit.ly/hackernoonlatestt">latest tech stories</a> and <a href="https://hackernoon.com/trending">trending tech stories</a>. Until next time, don’t take the realities of the world for granted!</blockquote><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c21ad6ebee1e" width="1" height="1" alt=""><hr><p><a href="https://medium.com/hackernoon/how-i-got-banned-from-codewars-c21ad6ebee1e">How I got banned from CodeWars</a> was originally published in <a href="https://medium.com/hackernoon">HackerNoon.com</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>