I started to learn how to use Grape. I have collection with a lot of attributes and want only some of them. I did something like this:
get :all_elements do
[
my_collection.each do |element|
{
id: element.id,
name: element.name
}
end
]
end
However this is not working. How can I create custom json array from collection?
Please try this code.
list = my_collection.map do |element|
{ :id => element.id,
:name => element.email
}
end
list.to_json
Related
I am creating API. Using ActiveRecords. Problem I am getting
Multiple array object of country, all I want one array containing all location
Current Output
{
"id": "180a096",
"country": [
{
"location": "US"
},
{
"location": "CH"
}
]
}
Expected Output
{
"id": "180a096",
"country": [
{"location":["US","CH"]}
]
}
Code
def as_json(options={})
super(:only => [:id ],:include => { :country => { :only => :location } })
end
Can anyone help me to restructured the object as in expected output.
If your hash is called hash you can do:
hash[:country].map {|h| h[:location]}
If you have to access attributes on associated models you can do:
countries.pluck(:location)
Unrelated to the question, but when I have to manage country info in my app I tend to use the countries gem. https://github.com/hexorx/countries
It has all kinds of useful helper methods, and it prevents you from having to maintain standardized country information.
You can simply map all the location and assign it to hash[:country]
2.4.0 :044 > hash[:country].map! { |c| c[:location] }
=> ["US", "CH"]
2.4.0 :045 > hash
=> {:id=>"180a096", :country=>["US", "CH"]}
As mentioned in my comment, you can do in one line like
actual_hash[:country].map! { |country| country[:location]}
actual_hash # => {:id=>"180a096", :country=>["US", "CH"]}
The output is clean but not as expected.
Or, a bit more lines to get the exact output:
location_array = [{location: []}]
actual_hash[:country].each { |country| location_array[0][:location] << country[:location]}
actual_hash[:country] = location_array
actual_hash # => {:id=>"180a096", :country=>[{:location=>["US", "CH"]}]}
def rearrange_json(input)
input_hash = JSON.parse(input)
output_hash = input_hash.clone
output_hash[:country] = {location: []}
input_hash[:country].map {|l| output_hash[:country][:location] << l[:location] }
output_hash.as_json
end
With this method, you can convert your json to a hash, then rearrange its content they way you want by adding the country codes as values for the [:country][:location] key of the output hash, and end up with some properly formatted json. It's not a one-liner, and probably not the most elegant way to do it, but it should work.
I need to do a json structure like this, but with more than 1 items:
charge = {
items: [{
name: "Product A",
value: 1000,
amount: 2
}]
}
I have an #items that is #items.pluck(:name, :price)
And I'm trying to create my json like this:
charge = {
items: [{
#items.each do |item|
'name:' = item.name,
'value:' = item.price,
'amount:' = 2
end
}]
}
And return this error:
SyntaxError in CoursesController#qualquer
syntax error, unexpected '=', expecting keyword_end
'name:' = item.name,
How i do this structure?
There are two things I see wrong. First, you're using "=" operator to set a Ruby Hash value. That's not correct, as Ruby hashes use symbols or strings. So your hash values will need to look like this:
{ "may_hash_key" => my.has_value }
or
{ my_hash_key: my.hash_value }
or
{ :may_hash_key => my.has_value }
Take your pick.
Additionally, if you are rendering JSON from your controller action, you can do something like this:
def index
# presumably some setup code
charge = {
items: #items.map do |item| {
name: item.name,
value: item.price,
amount: 2
} end
}
render json: charge
end
If you are not rendering JSON from your controller action, what you can do is set #charge and interact with it as a Ruby hash in your view instead.
I'm using Rails 3.2.18 and RABL 0.10.1.
Right now, I have many index actions through my application that include some pagination information, as well as the collection.
This is what an example of a rendered RABL response looks like:
{
"current_page" => 1,
"total_pages" => 1,
"total_count" => 2,
"per_page" => 1000,
"links" => [ {"id" => ...}, {"id" => ...}]
}
My config/initializers/rabl.rb looks like:
# config/initializers/rabl.rb
Rabl.configure do |config|
config.include_child_root = false
end
Here's what the index view for the above example response looks like:
# app/views/links/index.rabl
object false
node(:current_page) { #links.current_page }
node(:total_pages) { #links.num_pages }
node(:total_count) { #links.total_count }
node(:per_page) { #links.limit_value }
child(#links => :links) do
extends 'links/show'
end
I have the current_page, total_page, total_count, per_page nodes constructed like this for many index actions. I'd like to reduce the duplication.
I was hoping I could use a partial to make things like so:
# app/views/shared/pagination.rabl
node(:current_page) {|o| o.current_page }
node(:total_pages) {|o| o.num_pages }
node(:total_count) {|o| o.total_count }
node(:per_page) {|o| o.limit_value }
# app/views/links/index.rabl
object false
partial 'shared/pagination', object: #links
child(#links => :links) do
extends 'links/show'
end
But this winds up winds up throwing an error:
ActionView::Template::Error:
undefined method `current_page' for #<Link:0x007f92387dbc58>
I've read the RABL documentation and tried quite a few other methods based on what I read there, but I still can't figure out how to reduce the duplication and still have the original output.
Does anyone have an idea of how to accomplish this?
Thanks for your help and I'll gladly provide any more information that would help.
I have a dilema. There's a huge function in my controller to standardise loads of different types of data into one list for the view. So I have this kind of way of handling it at the moment:
customer.notes.each do |note|
to_push = {
id: note.id,
title: 'Contact Note',
type: 'note',
description: note.notes,
user: note.user,
date: note.date,
action: nil,
extras: note.customer_interests,
closed: false,
colour: '#9b59b6'
}
history.push to_push
end
I want to move that out of the controller into the model but I'm not too sure how. I ideally want a method like customer.notes.format_for_timeline but I can't figure out how to iterate over results like that in a self method within the class.
Thanks
I found out how. Using a self method then all:
def self.format
all.each do |item|
# Manipulate items here
end
end
However, I ended up having a method like this:
def format
{
id: id,
note: 'Contact Note',
# Etc
}
end
Then just used:
customer.notes.map {|i| i.format }
I want to write a method which will work like this one
def create_new_car(salon)
Car.create name: salon.offer.name, description: salon.offer.description, photo: salon.offer.photo, dealer_id: salon.dealer_id
end
but i want to keep it DRY. is there a way to pass those attributes by, i dont know, iterating through array of attributes by passing a block?
You can pass a block to create:
def create_new_car(salon)
Car.create do |car|
car.name = salon.offer.name
car.description = salon.offer.description
car.photo = salon.offer.photo
car.dealer_id = salon.dealer_id
end
end
You could also set some attributes as the first parameter and then pass a block:
Car.create(name: salon.offer.name) do |car|
car.description = salon.offer.description
#...
end
You can implement any logic you want inside that block to assign the Car properties, like this:
attributes = ["name", "description", "photo", "dealer_id"]
Car.create do |car|
attributes.each { |a| car.send( "#{a}=", salon.offer.send(a) )
end
Please try this
array_of_attrbiutes = [{name: salon.offer.name...}, {name: }, {}...]
def create_new_car(array_of_attributes)
Car.create array_of_attributes
end
end
Please see https://github.com/rails/rails/blob/b15ce4a006756a0b6cacfb9593d88c9a7dfd8eb0/activerecord/lib/active_record/associations/collection_proxy.rb#L259