Ordering JSON rendered by Rails controller - json

I have a Rails 3.1 controller that renders a user's contacts, including associated email objects and message objects. If I am only rendering the contacts, I can do the following:
#contacts = #current_user.contacts.order('last_name asc', :include => [:emails, :messages])
render json: #contacts, :include => [:emails, :messages]
As you can see, I want to sort the contacts by last name rather than the default id. I am now needing to render the user object with other associated objects as well. So I have tried the following, but of course the contacts are not in the appropriate order:
render :status => 200, :json => {
:user => #current_user.as_json(
:include => {
:foos => {
:except => :user_id
},
:contacts => {
:except => :user_id,
:include => [:emails,:messages]
},
:bars => {
:except => :user_id
}
}
)
}
I didn't see any help in the as_json documentation, and I haven't been able to find the right syntax by trial and error.

In this case I would order the contacts in Ruby / SQL and just build your own JSON to render instead of using as_json and its various :include / :except methods.
Build a hash of your data and then send it along to render.
There are all sorts of libraries that can make building JSON easier. JBuilder is one such library. Look at the bottom of the JBuilder page for links to other similar libraries.

Related

Display table data from RethinkDB in Phoenix Framework

I'm attempting to display data from my databases in RethinkDB (using the rethinkdb-elixir package from Hamiltop https://github.com/hamiltop/rethinkdb-elixir) in Phoenix. I'm relatively new to both, but I already managed to insert two tables and some data into those tables. I know this because I checked it through RethinkDB's web GUI.
Now I want to display table data in an html page of my project.
I've reduced the errors to one:
protocol Phoenix.HTML.Safe not implemented for %RethinkDB.Collection{data: [%{"first_name" => "Carlos", "id" => "4be8adc3-0973-45dc-bdb8-7a4dac6528d5", "last_name" => "Santos"}, %{"first_name" => "Carlos", "id" => "c84658fc-e4a4-4cb6-8107-b011ca996abd", "last_name" => "Santos"}, %{"first_name" => "Carlos", "id" => "c09fe081-379a-4334-97a3-31c5503c8c61", "last_name" => "Santos"}, %{"first_name" => "Carlos", "id" => "cf0c0ad3-3152-40f0-b613-5b051a314b51", "last_name" => "Santos"}, %{"first_name" => "Carlos", "id" => "ca28a714-ed54-4ebd-8707-d53170ead0f7", "last_name" => "Santos"}, %{"first_name" => "Carlos", "id" => "1ea77c0f-538c-4663-be92-499f16996594", "last_name" => "Santos"}, %{"first_name" => "Carlos", "id" => "1ea74846-0860-4ae5-95f5-674860cf7fc6", "last_name" => "Santos"}]}
Clearly it is fetching all the inserted Carlos Santos persons from the table (which I also must prevent but that is not my main issue) but having an error retrieving them to my Phoenix project.
I've got an index page in whose controller I create the tables and data.
Then I added a new page:
router.ex:
get "/users", UsersController, :users
/views/users_view.ex:
defmodule RethinkExample.UsersView do
use RethinkExample.Web, :view
end
users.html.eex:
<div class="jumbotron">
<p><%= #users %>!</p>
</div>
users_controller.ex
defmodule RethinkExample.UsersController do
use RethinkExample.Web, :controller
use RethinkDB.Query
def users(conn, _params) do
q = table("users")
|> filter(%{last_name: "Santos"})
|> RethinkExample.Database.run
|> IO.inspect
render conn, "users.html", users: q
end
end
I deduce that the html code is also incorrect, because this is how I would display the route specific id inside the html tags.
How can I fetch the data successfully and then display it in a html tag?
The problem here is that your data structure in #users is of type %RethinkDB.Collection{} (source) which cannot be output using <%=...%>
You will likely want to iterate over your users to output them. Something like:
<%= for user <- #users.data do %>
<p><%= "#{user["first_name"]} #{user["last_name"]}" %>!</p>
<% end %>
Here we are using a list comprehension to iterate over all the items on the #users.data array. This is a common way to output an array of elements (such as users, blog posts, comments, etc.) in EEx.
You might also want to consider passing q.data though as #users instead of q to prevent having to do #users.data.
As an aside, you can also use pattern matching inside the list comprehension:
<%= for %{"first_name" => first_name, "last_name" => last_name} <- #users.data do %>
<p><%= "#{first_name} #{last_name}" %>!</p>
<% end %>
This is useful if you don't plan on using many of the fields in the map.

REST and passing authentication token

I'm writing my first REST program and I'm struggling with passing the session token. Also I have looked in several forums for similar issues questions, but with no luck.
So I have the following piece of Ruby chunk code (not the whole script):
require 'rest-client'
require 'json'
headers_lbvserver = {
'Content-Type' => application/vnd.com.citrix.netscaler.lbvserver+json',
'accept' => :json
}
add_lbvserver = RestClient::Request.execute(
:method => :post,
:url => url_lbvserver,
:headers => headers_lbvserver,
:payload => payload_lbvserver,
:cookie => {'NITRO_AUTH_TOKEN=' => token_login}
)
So I have already received the token from a previous REST post, but I can't passing it trough when i maken my second call to the object. It comes with the following error: 400 Bad Request (RestClient::BadRequest)
After looking through the docs of RestClient, it looks like you are declaring your cookie incorrectly. You don't need to have an equal sign after the cookie name:
:cookie => {'NITRO_AUTH_TOKEN=' => token_login}
should be
:cookie => {'NITRO_AUTH_TOKEN' => token_login}

Render a view in a json object

I'm with Rails 4.
I'm trying to understand how to make my actions using ajax in my controller.
So I've created a method like that:
def create
#client = Client.new(client_params)
if #client.save
render :json => {:result => 'success' }
else
render :json => {:result => 'error', :template => (HERE MY PROBLEM) 'new' }
end
end
I want the function return a result state and in case there is a error, the view 'new'.
So, how can I inject a view generation as value of a json?
Thanks!
Ok, I found that
render :json => {:result => 'error', :template => render_to_string('new', layout: false) }

How do I set the default format, like JSON, for a customized Devise controller in Rails 3?

My Rails 3 app has three customized controllers for my Devise + OmniAuth integration. I needed to override the standard methods, like 'new', for user registrations and sessions. I specifically needed the controller methods to handle redirects and responses that are compatible with JSON formatting.
In my routes.rb file I have the following:
devise_for :users, :controllers => {
:omniauth_callbacks => "users/omniauth_callbacks",
:registrations => "users/registrations",
:sessions => "users/sessions"
}
That works as expected. My routes now show the custom controller routes like:
new_user_session GET /users/sign_in(.:format) {
:action =>"new",
:controller =>"users/sessions"
}
new_user_registration GET /users/sign_up(.:format) {
:action=>"new",
:controller=>"users/registrations"
}
To set the default format for a resource I would do something like this:
resources :users, :defaults => {
:format => 'json'
}
So, I tried this:
namespace "users" do
resources :registrations, :defaults => {
:format => 'json' }
resources :sessions, :defaults => {
:format => 'json' }
end
Which did not work as expected. I ended up with these routes:
new_users_registration GET /users/registrations/new(.:format) {
:format=>"json",
:action=>"new",
:controller=>"users/registrations"
}
new_users_session GET /users/sessions/new(.:format) {
:format=>"json",
:action=>"new",
:controller=>"users/sessions"
}
In order for this to work with my custom overrides in Devise, I need to format 'new_user_registration' not 'new_users_registration'.
I checked the 'devise_for' method and it does not have a :defaults option. I can use the 'devise_scope' method to set the individual routes, but that seems far less concise that the :defaults idiom.
Does anyone know of any routing magic that I can use to make this happen?
I found an answer that isn't necessarily satisfying, but it works. I tried this in routes.rb:
devise_scope :user do
get "sign_up", :to => "users/registrations#new",
:defaults => { :format => 'json' }
end
And I tried this in my custom controllers:
redirect_to new_user_registration_url, :format => 'json'
Neither worked. I am guessing both of those were incorrect in implementation. I finally used this in my custom controllers:
redirect_to :controller => 'users/registrations',
:action => 'new',
:format => 'json'
That replaced everywhere I originally had:
redirect_to new_user_registration_url
It's more verbose than I like and not very DRY, but it works.

rails joins conditions as hash

Course.find(:all, :group =>:id, :order => 'updated_at DESC', :joins=> :students :conditions => { :students => { :first_name=>"John", :status => 1}})
looking this query, passing the conditions as a hash, there is a way to:
construct a where :first_name not null?
construct a where :first_name != "John"?
Natively, there is not a way of which I am aware. There is ar-extensions which extends the finders with many things, including negating.
:conditions => { :students => { :first_name_not => "John"}}
:conditions => { :students => { :first_name_not => nil}}
Fair warning, last update I see for it is a year ago and support is limited to postgre, mysql and sqlite. This is the only active project I am aware of that extends activerecord in this way. Thoughtbot had squirrel, which you might be able to find some active forks for.