MIddleman foreach local object key not found - json

Here is my template.html.erb loop. I am trying to access the JSON object data. This works, if I use just straight json arrays, ["name","artist","details"] and access it via artwork[0] artwork[1] etc. However, Im trying to use a JSON object and things fall apart.
<% data.artworks.each_with_index do |artwork,index| %>
<div id="<%= slug_text artwork.name %>" class="port">
<div class="port_wrap">
<div class="grid">
<div class="c-50--lap-and-up grid__cell">
<div class="title-box">
<h1><%= artwork.name %></h1>
<h2>By: <%= artwork.artist %></h2>
Im getting "undefined method 'name' for #Array:0x000005584bcd3018 as an error.

Related

Keep formatting of object when passing EJS object from backend to frontend

Please excuse me if this is a very silly question (I am relatively new to web dev.)
I am trying to pass objects from backend (NodeJS) to frontend (EJS). The object itself is being passed but the formatting is not kept.
The object in NodeJS:
console.log(project.output)
Output:
866-981-4022
639-714-6905
184.118.7634
232-097-6927
(513) 480-5802
However when I do it in HTML/EJS:
<div> <%= detail.output %> </div>
It renders like this:
866-981-4022 639-714-6905 184.118.7634 232-097-6927 (513) 480-5802
How can I fix this? I want it to print/render like it does in NodeJS
You can add the style white-space: pre; to the div so the new lines are rendered as is.
<div style="white-space: pre;"> <%= detail.output %> </div>
<div style="white-space: pre;">866-981-4022
639-714-6905
184.118.7634
232-097-6927
(513) 480-5802</div>

Can't access deeply nested objects and arrays in EJS template

Hello fellow stackers,
I trying to get the following response to my EJS template.
Currently I have a for-loop which iterates all campaigns.
campaigns.facebook.data[i].insights .data
Just tried this, which works fully and the output is being shown below:
<% switch (campaigns.facebook.data[i].status) {
case 'ACTIVE' : %>
<div class="ui grid">
<p><%- JSON.stringify(campaigns.facebook.data[i].insights) %></p>
...
However, while trying to get the .data object I encounter problems
<p><%- JSON.stringify(campaigns.facebook.data[i].insights.data) %></p>
Even while trying JSON.stringify(campaigns.facebook.data[i].insights.data[0]) doesn't give any luck. What is possibly wrong here?
After adding a conditional statement for checking if the desired object exist, we won't encounter the undefined error anymore.
<% if (campaigns.facebook.data[i].insights) { %>
<p><%- JSON.stringify(campaigns.facebook.data[i].insights.data[0]) %></p>
<%console.log(campaigns.facebook.data[i].insights.data[0])%>
% } %>

The "show" page isn't displaying the property of the correct data

I'm making a website using ror and I have a list of fandoms, and I want to display different pictures and writing for that fandom. Right now, just for testing, I'm having it just display the name of the fandom at the top of the page, but no matter which one I click on, it only displays the name of the first fandom. Here's the parts of the files I think are relevant, but if you need to see more, I'll post it.
Section of routes.rb:
get 'fandoms' => 'fandoms#index'
get 'fandoms/new' => 'fandoms#new'
post 'fandoms' => 'fandoms#create'
get 'fandoms/:id' => 'fandoms#show', as: :fandom
resources :fandoms
The show method in fandoms_controller:
def show
#fandom = Fandom.find_by(params[:id])
end
The index.html.erb for fandoms:
<div class="main">
<div class="container">
<h2>Fandoms</h2>
<%= link_to "New Fandom (dev only)", "fandoms/new" %>
<% #fandoms.each do |fandom| %>
<div class="fandoms">
<%= link_to fandom.name, fandom_path(fandom) %>
</div>
<% end %>
</div>
And finally the show.html.erb for fandoms:
<div class="main">
<div class="container">
<h2>Fandoms</h2>
<div class="fandom">
<h1><%= #fandom.name %></h1>
</div>
</div>
</div>
I double checked my code with the Ror tutorial on codecademy, but I still couldn't find any differences for what I wanted to do.
Thanks.
Your show action has a subtle typo that's breaking your logic:
#fandom = Fandom.find_by(params[:id])
Should actually be:
#fandom = Fandom.find(params[:id])
The difference is, find_by will return the first row for which the conditions passed are met. You're not actually passing any conditions; just an ID, which in Postgres doesn't even work:
irb> Fandom.find_by(1)
PG::DatatypeMismatch: ERROR: argument of WHERE must be type boolean, not type integer
LINE 1: SELECT "fandoms".* FROM "fandoms" WHERE (1) LIMIT 1
Your database is more permissive, but seems to be treating it just as a WHERE TRUE clause and thus every single row meets the condition. As such, it returns the first row every time. Using find(id) will give you the desired result.

How can I ensure that my Backbone forms return data that's formatted the same way as it came in?

In short:
When using Backbone and Underscore templates, what's the best way to ensure that the data in a form is formatted in the exact same way when POSTed to the server as it was when it was initially fetched?
Longer question:
I'm currently using Backbone’s fetch() to retrieve some data from the server as JSON. On success I'm taking that JSON and using the data in an Underscore template like so:
<div class="module-content">
<form>
<div class="customer-primary">
<% if (ParentCompany) { %>
<div class="row">
<div class="label">Parent Company</div>
<div class="value">
<div class="current-value"><%= ParentCompany %></div>
<div class="editable-value"><input name="ParentCompany" value="<%= ParentCompany %>"></div>
</div>
</div>
<% } %>
<% if (Title) { %>
<div class="row">
<div class="label">Title</div>
<div class="value">
<div class="current-value"><%= Title %></div>
<div class="editable-value"><input name="Title" value="<%= Title %>"></div>
</div>
</div>
<% } %>
…
</div>
</form>
</div>
The JSON has a number of children with multiple entries, like this:
{
"UserID":"12345",
"FirstName":"Brandon",
"Ship": {
"Address1":"33 One Two Ave",
"Address2":"#23D",
"Address3":"",
"City":"New York",
"State":"NY",
"Country":"United States",
"Zip":"10023"
},
"Phones": [
{
"Kind":"Tel",
"Number":"512-123-4567"
},
{
"Kind":"Fax",
"Number":"512-123-4567"
}
]
}
How can I ensure that I build the form out in such a way that it returns an object that's formatted in the same way for easy DB updates?
Please let me know if you need more info!
If I understand your question, you're trying to make sure the JSON data structure matches what the server expects when you're sending data. (And coincidentally, that it's in the same structure that you received from the server.)
What you want to do is override the model's toJSON function so your data is serialized as expected. Then, when it gets persisted by Backbone.sync, the proper data structure will be sent to the remote API.
Take a look at these:
Saving Backbone model and collection to JSON string
backbone.js: overwritting toJSON
I think the best you can do is to validate your model. and make the fields that you need to be sent required, if you need all of them ,then validate your entire model.
This plugin is a good option for this task.
https://github.com/fantactuka/backbone-validator

Div Tables with ASP.NET MVC

I'm trying to find a better way to use a div table with ASP.NET MVC, the problem I see is that you need to do loads of looping, rather than one loop if I had to use a traditional <table> table.
Example
<div class="column">
<div class="row">Name</div>
<% foreach (Person person in (List<Person>)ViewData.Model) {%>
<div class="row"><%= Html.Encode(person.Name) %></div>
<%} %>
</div>
<div class="column">
<div class="row">Email</div>
<% foreach (Person person in (List<Person>)ViewData.Model) {%>
<div class="row"><%= Html.Encode(person.Email) %></div>
<%} %>
</div>
<div class="column">
<div class="row">Phone</div>
<% foreach (Person person in (List<Person>)ViewData.Model) {%>
<div class="row"><%= Html.Encode(person.Phone) %></div>
<%} %>
</div>
If it looks like a table and smells like a table why not use a table?
But if you want to do it in this way well try to build a extention method for your Html property that generates this html code and have the list as a parameter and maybe a list for your columns, To generate your html code you can use the TagBuilder class.
It's rather subjective issue, but I think you don't really need to use divs to do so, coz you are simply displaying table of data and this is why we need "table" tag.
The introduction of div and CSS layout is not to replace the table tag, but to free table tag from doing formatting and layout job.
Edit
Moreover, you can still do your job in one loop. Rather than loop through columns, why not loop through rows (name, phone... )
<% foreach(Person person in (List<Person>)ViewData.Model)) %>
<div class="row">
Name: <%= Html.Encode(person.Name) %>
Email: <%= Html.Encode(person.Email) %>
...
</div>
Although I personally still prefer using table (together with tr and td) instead.
If you are dislaying tabular data, that's why the table tag is there. People only suggest div, instead of table when it's about layout. So it's perfectly OK to use the table tag when you are displaying key-value type of information.
I agree with what everyone else have said (that you really should just use a table) - however I will try to come up with a solution to your issue too.
I don't think there's an elegant way to overcome the "loop more than once" issue, but at the very least we can make it a bit "easier" to add new columns to the list:
var myList = (List<Person>)ViewData.Model;
var myColumns = new Dictionary<string, List<string>>();
myColumns.Add("Name", new List<string>());
myColumns.Add("Email", new List<string>());
myColumns.Add("Phone", new List<string>());
foreach(var person in myList){
myColumns["Name"].Add(Html.Encode(person.Name));
myColumns["Email"].Add(Html.Encode(person.Email));
myColumns["Phone"].Add(Html.Encode(person.Phone));
}
Then now you can do this:
<% foreach(var column in myColumns){ %>
<div class="column">
<div class="row"><%= column.Key %></div>
<% foreach (string value in column.Value) {%>
<div class="row"><%= value %></div>
<%} %>
</div>
<% } %>
It is still poor performance compared to using the -tag and really I don't see why you'd want to avoid that in this scenario.