JustusP JustusP - 6 months ago 20
Ruby Question

How do I parse values from a controller back to yaml?

I have a form in my application.html.erb:

<%=form_tag("/parse_input", method: "post") do %>
<%= text_field(:ans, :field) %>
<%= text_field(:ans1, :field) %>
<%= text_field(:ans2, :field) %>
<%= submit_tag("submit") %>
<%end%>

<%= @ans.to_s %>


which is parsed in form_controller.rb:

class FormController < ApplicationController
def parse_input
params[:ans].each do |value|
render :template => "layouts/application.html.erb", :locals => {value => value.upcase}
end
end
end


I want to write the form values to a YAML file. I set up a dummy function in my application.html.erb that successfully generates a YAML from a hash. How do I generate a YAML with the form values?

Answer Source

Use Ruby File.

Add File.open() in your controller parse_input action1:

File.open(Rails.root.join('data', 'answers.yaml'), 'a') do |file|
  file << params.to_yaml
end

This code will create an answers.yaml file in /data directory2 (check open options here) and append all your params to it (in yaml format).

Consider that params.to_yaml will include all parameters in params, so your file will look something similar to this:

--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  utf8: "✓"
  authenticity_token: fdUblOU+QL/daIdRoa94IbOjm0RWL/ugABsEYsdfem/Pt+N5hCSMQpfMVWanfqCHoX4WDPfTEUuVsNSJsnuvyQ==
  ans: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
    field: answer1
  ans1: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
    field: answer2
  ans2: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
    field: answer3
  commit: submit
  controller: form
  action: parse_input
permitted: false

So you may want to filter params before creating the file, and you can accomplish that by, first, changing how you name your input tags:

<%=form_tag("/parse_input", method: "post") do %>
  <%= text_field(:answers, :ans1) %>
  <%= text_field(:answers, :ans2) %>
  <%= text_field(:answers, :ans3) %>
  <%= submit_tag("submit") %>
<%end%>

This will generate a form which input names will be grouped in answers, for example, the first input name will be answers[ans1].

Now you can access only the answers parameters with params[:answers] (this will filter out anything out of that group, e.g. commit, controller, action, etc.); but we still need more filtering, since params[:answers].to_yaml will output:

--- !ruby/object:ActionController::Parameters
parameters: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  ans1: answer1
  ans2: answer2
  ans3: answer3
permitted: false 

So, as second step, call as_json before calling to_yaml; this will convert the ActionController::Parameters object to json format, removing the extra parameters (i.e. parameters, permitted), so

File.open(Rails.root.join('data', 'answers.yaml'), 'a') do |file|
  file << params[:answers].as_json.to_yaml
end

will create the following answers.yaml file;

---
ans1: answer1
ans2: answer2
ans3: answer3

Notes

1 It could be better if you create a private method within your controller, and call that method in your action.

2 The directory you choose (data in the example) should be created first.