ReidasaurusRex ReidasaurusRex - 1 month ago 17
React JSX Question

Managing related Models in Rails with React

I have the following data relations:

NewsfeedItem.rb
has_many :comments
has_many :likes

Like.rb
belongs_to :newsfeed_item

Comment.rb
belongs_to :newsfeed_item


In html.erb files, managing these relations was easy. For example:

# in newsfeed_items/index.hmtl.erb
<% @newsfeed_items.each do |item| %>
<div>

<div>
<h2><%= item.title %></h2>
<p><%= item.content %></p>
</div>

<p>Likes: <%= item.likes.length %></p>

<ul>
<% item.comments.each do |comment| %>
<li><%= comment.text %></li>
<% end # comments.each %>
</ul>

</div>
<% end # newsfeed_items.each%>


However, I'm struggling with how to properly separate concerns when I want to extrapolate this into React. Current newsfeed_items component:

# in components/newsfeed_items.jsx
var NewsfeedItems = React.createClass({
getInitialState: function() {
return {items: []};
},
loadItems: function() {
$.ajax({
url: this.props.url,
dataType: 'json',
type: 'GET',
success: function(data) {
this.setState({items: data});
}.bind(this)
});
},
componentDidMount: function() {
this.loadItems();
},
render: function() {
var items = this.state.data.map(function(item) {
return (<NewsfeedItem key={item.id} title={item.title} content={item.content} />
});
return (
<div className="c-newsfeed-list">
{items}
</div>
);
}
});


This component retrieves items from the
newsfeed_items_controller
:

# in newsfeed_items_controller.rb
def index
respond_to do |format|
format.html
format.json {render json: @newsfeed_items}
end
end


It seems like I'd be mixing concerns if I attached the
likes
and
comments
of the
newsfeed_items
to the json returned from
newsfeed_items_path
. Yet, setting separate ajax calls for each
newsfeed_item
to GET its correlating
likes
and
comments
seems unnecessary.

Which is best practice / best solution?

Answer

You are right that multiple API calls are unnecessary. Here are two alternatives I have used in production:

  1. JSON Builder Gem This allows you to pass customized associated objects along with your main object through an API
  2. Overwrite the as_json method within the model to incorporate your associated objects. By default render json: @newsfeed_items calls @newsfeed_items.to_json so by overwriting the method to include it's associations, you can get whatever you want.