Ruby On Rails | What is format.html/json for? - html

So I have been going through Rails Zombies and have gotten to the part explaining format.html and .json
My question is what do these lines of code do, and why do we have them? If I write these methods or actions without these format codes they work perfectly fine, as i'd assume they simply display in html format by default? If somebody could clear up exactly what this code does I'd be grateful, I also do not fully understand what JSON is.
def create
#zombie = Zombie.new(zombie_params)
respond_to do |format|
if #zombie.save
format.html { redirect_to #zombie, notice: 'Zombie was successfully created.' }
format.json { render :show, status: :created, location: #zombie }
else
format.html { render :new }
format.json { render json: #zombie.errors, status: :unprocessable_entity }
end
end

In simple terms:
If the request wants an HTML page, it will perform the instructions set by the block given to format.html.
If the request wants application/json (like when you make an Ajax request), the response will be given as instructed in the block given to format.json.
You should know what JSON means before delving into creating any web service. See http://www.json.org/

Related

Rails How Can I Iterate Over JSON Field

I'm trying to play around with DALLĀ·E 2 and what I'm trying to do is simply call their image creation API and display the images using the image URLs they return.
I'm getting stuck on how to show the images on my web page based on the JSON response.
What I've done is save the response in a JSON attribute for my ImageRequest model.
So my code looks like this:
def new
#image_request = ImageRequest.new
end
def create
#image_request = ImageRequest.new(image_request_params)
client = OpenAI::Client.new(access_token: "my_key")
response = client.images.generate(parameters: { prompt: #image_request.prompt, n: #image_request.versions })
#image_request.urls = response
respond_to do |format|
if #image_request.save
format.html { redirect_to image_request_url(#image_request), notice: "Image request was successfully created." }
format.json { render :show, status: :created, location: #image_request }
else
format.html { render :new, status: :unprocessable_entity }
format.json { render json: #image_request.errors, status: :unprocessable_entity }
end
end
end
def show
#image_request = ImageRequest.find(params[:id])
end
But what I'm trying to determine is how can I parse and iterate the JSON and show the images?
# in psuedo code what I'm trying to do:
<% images.each do |i| %>
<%= image_tag "url" %>
<% end %>
This is what the OpenAI response is:
{
"created": 1674850160,
"data": [
{
"url": "https://oaidalleapiprodscus.blob.core.windows.net/private/...."
},
{
"url": "https://oaidalleapiprodscus.blob.core.windows.net/private/..."
}
]
}
When I look at the stored value in the JSON attribute (after create) in #image_request.urls, it's:
{"created"=>1674850160, "data"=>[{"url"=>"https://oaidalleapiprodscus.blob.core.windows.net..."}, {"url"=>"https://oaidalleapiprodscus.blob.core.windows.net/private/..."}]}
I've looked at these SO questions and experimented, but I can figure out how to just iterate through the data.url(s) returned.
Iterating over JSON in Rails
How do I parse JSON with Ruby on Rails?
Access JSONB fields as normal ActiveRecord attributes
Iterating over JSON in Rails
Loop through API response with .each
If response is {"created"=>1674850160, "data"=>[{"url"=>"https://oaida... then the JSON has already been parsed for you into a Ruby data structure. You then need to turn that into a list of URLs.
Pluck each "url" value from the Hashes in the "data" Array.
#image_request.urls = response["data"].pluck("url")
Now you have an Array of URLs which you can iterate through.
<% image_request.urls.each do |url| %>
<%= image_tag(url) %>
<% end %>

Send an http response to another site

Noob
How should I send a single string variable to another site from my rails app? ie the outside service sends a get request to my controller/route and then the controller must respond with the string (and I assume a response code). The string is intended to be added to their html code.
In my controller should I
render :text => "string"
or
respond_with("string) #as xml or json
or something completely different?
Just try the following code. Here your application gives the text and json as per the request.
respond_to do |format|
format.json do
render :json => 'string'
end
format.html do
render :text => 'string'
end
end

Show data after AJAX call, how to render in controller?

I would like to use link_to to call a controller action named show. This happens, I get a 200 message. Now I want to update a div with the content that is being returned.
Code in controller:
respond_to do |format|
format.html # show.html.erb
format.js
end
Code in view, link and JavaScript:
<%= link_to "Show analysis", company_comparison_path(3), :remote => true , :id => "thelink" %>
<div id="replaced"> will be replaced </div>
<script>
$('#thelink').bind('ajax:complete', function() {
$('#replaced').html(data)
});
</script>
I think I still don't understand how to return the HTML or JavaScript from the controller properly into the JavaScript. If I replace the word "data" in the JavaScript with some text in brackets, I get proper output. But how do I get the result from the controller action?
You were almost there, but you need to tell the bound function what the actual html content is you want to insert into your #results div. When you call .html() on $('#replaced') the variable you use (data) is still undefined.
Try the following:
$('#thelink').bind('ajax:complete', function(event, data) {
$('#replaced').html(data.responseText);
});
edit: Oh, something to keep in mind is that this may render your view including the layout which is probably not what you want. You can add something like render layout: false if request.xhr? to your controller to prevent the layout from showing up on ajax requests.
If you want to return richer content from the AJAX response, you can render the view from the controller by the :render_to_string method.
See more: http://apidock.com/rails/ActionController/Base/render_to_string
respond_to do |format|
format.html # show.html.erb
format.js {
#content = render_to_string(:partial => 'some_partial_view')
}
end

Rails routing - how to add .html extension to the routing rule?

I have this rule:
match '*urlnames' => 'home#searching_names'
The URL address looks like website.com/john.html.
The problem is, that in the log I see
Parameters: {"urlnames"=>"john"}
without the .html extension. Text extension is important, I would need to test it in the controller.
I tried to add to the routing rule this part:
match '*urlnames' => 'home#searching_names', :defaults => { :format => "html" }
But still the same, in the log is
Parameters: {"urlnames"=>"john"}
How can I catch the extension in the controller?
You have access to the requested format via request.parameters[:format] or (as a MIME type) via request.format.
However, you can also use a respond_to block:
def show
file = params[:urlnames]
respond_to do |format|
format.html { ... }
format.txt { ... }
end
end
where ... is code to render some text, or send some data or a file.
If you're just trying to show some static files, just place them in the public dir, and bypass Rails entirely.

respond_with redirecting when format=json

I'm encountering a strange behavior in my controllers. They seem to occasionally want to redirect instead of render a json response.
respond_to :json, :html, :js
def create
#favorite = current_user.favorites.build(:location_id=>params[:location_id])
if #favorite.save
respond_with(#favorite)
else
respond_with(#favorite.errors)
end
end
I think it works most of the time but today I was notified of this error:
NoMethodError: undefined method `favorite_url' for #<FavoritesController:0x00000006171dc0>
The params hash was logged as:
{"format"=>"json",
"action"=>"create",
"user_id"=>"56",
"auth_token"=>"iGSty8CMIaWsbShYZEtw",
"location_id"=>"47943",
"controller"=>"favorites"}
Especially strange since it seems to work most of the time... I have changed a few of my other controllers to use the old format.json { render :json => #object } syntax but I'd like to avoid that if possible.
How could this be?
On paths that are not GETs, respond_with tries to redirect to the url for whatever it is given. You can override this with a custom Responder