title: How to create requests params for json api resources in requests tests?
body: <p>I'm creating a API with Rails 6 and JSON API Resource in order to learn more. I got stuck with requests tests. What I'm doing for now is using the gem <a href="https://github.com/thoughtbot/json_matchers" rel="nofollow noreferrer">json_matchers</a> to test the response of my endpoint, but my real problem is to build the body of requests for: post, put and patch. </p>
  
  <p>Hi, thanks for you attention.</p>
  
  <p>Here is the deal, I started adding to my RSpec files all the json needed for the tests, but these files ended up getting too big. So I thought, how can I makes this to stay more lean?</p>
  
  <p>Then I copy all the json in my tests to json files and importing when needed, for example:</p>
  
  <pre><code># RSpec Helper
  def request_json(json_name)
    request_directory = "#{Dir.pwd}/spec/support/api/requests"
    request_path = "#{request_directory}/#{json_name}.json"
    File.read(request_path)
  end
  
  # Example of params for user request
  let(:params) { request_json("user") }
  </code></pre>
  
  <p>I thoutgh it was a great idea, but then I ran into two problems: I need to create a file for every request test and... how I will modify same value of this json file at runtime? For example, I create a object using FactoryBot and now I need to use the ID of this object in my request for a update. How can I do that?</p>
  
  <p>Using regex?</p>
  
  <pre><code>let(:params) do 
    json = request_json("user")
    json.gsub(/\"id\": \"1\"/, "\"id\": \"#{id}\"")
  end 
  </code></pre>
  
  <p>Ok... It works, but I don't like it! I think that this can turn to be a real mess. Another options was to convert this to hash and then json again... Nope, nope, nope, don't like it either.</p>
  
  <p>Now I'm trying to create something more dynamic using FactoryBot and Faker. For now, with the code below, I can pass a factory name and receive a perfect json body for a post.</p>
  
  <pre><code>def serializer_for(resource)
    {
      "data": {
        "type": resource.to_s.tableize,
        "attributes": create_attributes_for(resource),
      }
    }.to_json
  end
  
  def create_attributes_for(resource)
    attributes = attributes_for(resource)
    attributes.reduce({}) do |hash, element|
      hash.update(standardize_json_key() =&gt; element.last.to_s)
    end
  end
  
  def standardize_json_key(symbol)
    symbol.to_s.gsub("_", "-")
  end
  </code></pre>
  
  <p>But then I began to think about the challenges of this approach:</p>
  
  <ul>
  <li>Post/Put/Patch with relationships?(has_one or has_many)</li>
  <li>How I'll add the ID field for put/path?</li>
  <li>Add how I'll add the upload files when needed?</li>
  </ul>
  
  <p>So... returning to my question: How can I prepare the json body for the request using <code>factory bot</code> (using even <code>traits</code>) with all the concerns above?</p>
  
  <p>If you have/know a better answer for this problem, share with, please. If not, I'll try to create a gem for this.</p>
  
  <p>Appreciate your time, thanks!</p>