I have an index action in my controller that I use to render all posts as JSON:
def index
#user = current_user
#posts = Post.all
end
respond_to do |format|
format.html
format.json {
render json: #posts.to_json(:include => {
:user => { :only => [:first_name, :last_name]},
:category => { :only => [:name, :id]}
}),
:callback => params[:callback]
}
end
end
What I'd like to do, is add an additional attribute to each post's JSON output called posted_on, that has a value of: distance_of_time_in_words(post.created_at, Time.now)}
I can't seem to be able to figure out how to approach this. Any help would be appreciated!
Add the method posted_on to Post model
class Post < ActiveRecord::Base
include ActionView::Helpers::DateHelper
def posted_on
distance_of_time_in_words(created_at, Time.now)
end
end
In your controller, pass the methods option to to_json
def index
#user = current_user
#posts = Post.all
end
respond_to do |format|
format.html
format.json {
render json: #posts.to_json(:include => {
:user => { :only => [:first_name, :last_name]},
:category => { :only => [:name, :id]}
}, :methods => :posted_on),
:callback => params[:callback]
}
end
end
Related
I'm fairly new to API in Rails, and so I will need some assistance for the issue that I am facing.
All I want is to create a record on the database of the API through a POST request from my application.
That is to create a record on both databases (my database and the on the database of the API through a POST request from my application) whenever I create a book.
So this is what I've done so far:
For the app that will consume the API I am using the HTTParty gem.
I have tried to implement in my create action of the Books Controller using the code below:
#result = HTTParty.post(' https://www.pingme.com/wp-json/wplms/v1/user/register',
:body => { :name => '#{name}',
:author => '#{author}',
:description => '#{description}',
:category_id => '#{category_id}',
:sub_category_id => '#{sub_category_id}'}.to_json,
:headers => { 'Content-Type' => 'application/json', 'Authorization' => '77d22458349303990334xxxxxxxxxx' })
Here is my Books Controller for creating books
require 'httparty'
class BooksController < ApplicationController
include HTTParty
before_action :set_book, only: [:show, :edit, :update, :destroy]
before_action :authenticate_admin!, except: %i[show index]
skip_before_action :verify_authenticity_token
# GET /books
# GET /books.json
def index
#books = Book.search(params[:keywords]).paginate(:page => params[:page], :per_page => 9).order('created_at DESC')
end
# GET /books/1
# GET /books/1.json
def show
end
# GET /books/new
def new
#book = Book.new
end
# GET /books/1/edit
def edit
end
# POST /books
# POST /books.json
def create
#book = Book.new(book_params)
respond_to do |format|
if #book.save
format.html { redirect_to #book, notice: 'Book was successfully created.' }
format.json { render :show, status: :created, location: #book }
else
format.html { render :new }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
#result = HTTParty.post(' https://www.pingme.com/wp-json/wplms/v1/user/register',
:body => { :name => '#{name}',
:author => '#{author}',
:description => '#{description}',
:category_id => '#{category_id}',
:sub_category_id => '#{sub_category_id}'}.to_json,
:headers => { 'Content-Type' => 'application/json', 'Authorization' => '77d22458349303990334xxxxxxxxxx' })
end
# PATCH/PUT /books/1
# PATCH/PUT /books/1.json
def update
respond_to do |format|
if #book.update(book_params)
format.html { redirect_to #book, notice: 'Book was successfully updated.' }
format.json { render :show, status: :ok, location: #book }
else
format.html { render :edit }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
end
# DELETE /books/1
# DELETE /books/1.json
def destroy
#book.destroy
respond_to do |format|
format.html { redirect_to books_url, notice: 'Book was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_book
#book = Book.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def book_params
params.require(:book).permit(:name, :author, :description, :category_id, :sub_category_id)
end
end
But it still doesn't create these books on the database of the API through the post request when I create books.
Please any form of assistance will be highly appreciated.
Thank you.
Check you logs when you do the request, but I suspect you need to change your body to:
{
:book => {
:name => '#{name}',
:author => '#{author}',
:description => '#{description}',
:category_id => '#{category_id}',
:sub_category_id => '#{sub_category_id}'
}
}.to_json
Note that book key at the top is the difference.
Following contributions from #paulo-fidalgo and #tejasbubane, I found a working solution to the issue.
Here is the corrected HTTParty Post Request
#results = HTTParty.post(' https://www.pingme.com/wp-json/wplms/v1/user/register',
:body => {
:name => "#{#book.name}",
:author => "#{#book.author}",
:description => "#{#book.description}",
:category_id => "#{#book.category_id}",
:sub_category_id => "#{#book.sub_category_id}"}.to_json,
:headers => {
'Content-Type' => 'application/json',
'Authorization' => '77d22458349303990334xxxxxxxxxx'
}
)
I'm sending the following JSON to Rails 4.1.0
Started POST "/orders.json" for 127.0.0.1 at 2015-08-11 15:19:34 +0200
Processing by OrdersController#create as JSON
Parameters: {"order"=>{"name"=>"Jon", "surname"=>"Do", "line_items_attributes"=>[{"work_id"=>16, "quantity"=>1, "total_price"=>34.5}, {"work_id"=>12, "quantity"=>2, "total_price"=>40}]}}
Unpermitted parameters: line_items_attributes
but I'm getting Unpermitted parameters error. My Order model:
class Order < ActiveRecord::Base
belongs_to :user
belongs_to :dispatch_method
belongs_to :payment_method
has_many :line_items, :dependent => :destroy
accepts_nested_attributes_for :line_items
end
My orders_controller.rb
class OrdersController < ApplicationController
before_action :set_order, only: [:show, :edit, :update, :destroy]
def index
#orders = Order.all
end
def show
end
def new
#order = Order.new
end
def edit
end
def create
#order = Order.create(order_params)
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render action: 'show', status: :created, location: #order }
else
format.html { render action: 'new' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #order.update(order_params)
format.html { redirect_to #order, notice: 'Order was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
def destroy
#order.destroy
respond_to do |format|
format.html { redirect_to orders_url }
format.json { head :no_content }
end
end
private
def set_order
#order = Order.find(params[:id])
end
def order_params
params.require(:order).permit(:name, :surname, line_items_attributes: [:id, :work_id, :quantity, :total_price])
end
end
I'm able to create and save a new instance of order, but not of a line_item.
You can try to redefine your order_params like this:
def order_params
json_params = ActionController::Parameters.new(JSON.parse(params[:order]))
return json_params.require(:name, :surname).permit(line_items_attributes: [:id, :work_id, :quantity, :total_price])
end
As you see, I am parsing params[:order] to avoid parsing the full params var. You might need to add another json level here but I hope you get the idea.
something like this
render :json => #booking, :include => [:paypal,
:boat_people,
:boat => {:only => :name, :include => {:port => {:only => :name, :include => {:city => {:only => :name, :include => {:country => {:only => :name}}}}},
:boat_model => {:only => :name, :include => {:boat_type => {:only => :name}}}}}]
I have a controller 'news_controller.rb' for interfacing with a database. When I try to create a database row item (I do it by an automated script making post requests), I get the following error
ActionController::ParameterMissing (param is missing or the value is empty: news): app/controllers/api/news_controller.rb:57:in `news_params'app/controllers/api/news_controller.rb:28:in `create'
When I use params[:category], params[:headline] etc., inside the create action, then it works fine. What are the possible causes and solutions for this?
Here's my controller code:
module Api
class NewsController < Api::ApiController
respond_to :json
def index
#news = News.all
respond_with :news => #news
end
def show
#news = News.find(params[:id])
respond_with :news => #news
end
def new
#news = News.new
respond_with :news => #news
end
def edit
#news = News.find(params[:id])
respond_with :news => #news
end
def create
if !News.exists?(headline: params[:headline])
##news = News.new(:category => params[:category], :headline => params[:headline], :content => params[:content], :image_url => params[:image_url])
#news = News.new(news_params)
if #news.save
respond_with :news => #news
else
respond_with #news.errors
end
end
end
def update
#news = News.find(params[:id])
if #news.update(news_params)
respond_with :news => #news
else
respond_with #news.errors
end
end
def destroy
#news = News.find(params[:id])
#news.destroy
respond_to do |format|
format.json { head :no_content }
end
end
private
def news_params
params.require(:news).permit(:category, :headline, :content, :image_url)
end
end
end
Your params has value
params = { category: 'value', headline: 'value', .... }
When you use news_params you expect your params to be formatted like
params = { news: { category: 'value', headline: 'value', .... }}
But that is not the case.
This is why it works when you use
#news = News.new(:category => params[:category], :headline => params[:headline], :content => params[:content], :image_url => params[:image_url])
And does not work with
#news = News.new(news_params)
# news_params is nil
I have a simple has_one relationship setup but I want to add records to Damages table only when the text_field is not blank or nil. Right now it's adding records that are blank or nil to the other table.
My view:
<%= f.fields_for :damage do |builder| %>
<%= builder.label 'Damage' %><br />
<%= builder.text_field :dam_detail %>
<% end %>
Packjob Model:
class Packjob < ActiveRecord::Base
attr_accessible :pj_damage
has_one :damage
accepts_nested_attributes_for :damage
end
Damage Model:
class Damage < ActiveRecord::Base
attr_accessible :dam_detail
belongs_to :packjob
end
How do I allow only non blank or nil values being added?
Is best practice to add logic for this to the helper?
EDIT:
Here's the controller for Packjobs:
class PackjobsController < ApplicationController
# GET /packjobs
# GET /packjobs.json
def index
#packjobs = Packjob.includes(:damage).all
#packers = Packer.find(:all)
#rigs = Rig.find(:all, :order => "rig_type_number")
respond_to do |format|
format.html # index.html.erb
format.json { render json: #packjobs }
end
end
# GET /packjobs/1
# GET /packjobs/1.json
def show
#packjob = Packjob.find(params[:id])
#packers = Packer.find(:all)
respond_to do |format|
format.html # show.html.erb
format.json { render json: #packjob }
end
end
# GET /packjobs/new
# GET /packjobs/new.json
def new
#packjob = Packjob.new
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
#damage = #packjob.build_damage
##book = #author.build_book
respond_to do |format|
format.html # new.html.erb
format.json { render json: #packjob }
end
end
# GET /packjobs/1/edit
def edit
#packjob = Packjob.find(params[:id])
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
end
# POST /packjobs
# POST /packjobs.json
def create
#packjob = Packjob.new(params[:packjob])
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
respond_to do |format|
if #packjob.save
format.html { redirect_to #packjob, notice: 'Packjob was successfully created.' }
format.json { render json: #packjob, status: :created, location: #packjob }
else
format.html { render action: "new" }
format.json { render json: #packjob.errors, status: :unprocessable_entity }
end
end
end
# PUT /packjobs/1
# PUT /packjobs/1.json
def update
#packjob = Packjob.find(params[:id])
#packers = Packer.find(:all, :conditions => { :p_team => "t" }, :order => "p_name")
#rigs = Rig.find(:all, :conditions => { :rig_status => "t" }, :order => "rig_type_number")
respond_to do |format|
if #packjob.update_attributes(params[:packjob])
format.html { redirect_to #packjob, notice: 'Packjob was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #packjob.errors, status: :unprocessable_entity }
end
end
end
# DELETE /packjobs/1
# DELETE /packjobs/1.json
def destroy
#packjob = Packjob.find(params[:id])
#packjob.destroy
respond_to do |format|
format.html { redirect_to packjobs_url }
format.json { head :no_content }
end
end
end
Also the I want the packjob to allow for blanks in damage text_field, I just don't want the records added to the Damages table..
This is a job for validations. Specifically, you want two things:
You want your Damage class to validate that :dam_detail is not blank or nil:
class Damage < ActiveRecord::Base
# ... rest of class here ...
validates :dam_detail, :presence => true, :length => { :minimum => 1 }
end
You want your Packjob class to validate that its contained Damage object is valid:
class Packjob < ActiveRecord::Base
# ... rest of class here ...
validates_associated :damage
end
I also recommend modifying your database schema to add the restriction that the dam_detail field cannot be null. See the migrations guide for more info.
Even though its more commonly used for has_many the cocoon gem https://github.com/nathanvda/cocoon is great for this. That gem will allow you to build the relation on the fly from the front end. it will also allow you to destroy the relation too.
I use rails 2.3.8
def index
#posts = Post.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => ({ :results => #posts.size, :rows => #posts.to_json(:only => [:id, :title, :click_count, :body])}).to_json }
end
end
the generated json data is:
{"rows":"[{\"title\":\"ruby\",\"body\":\"goood\",\"click_count\":1,\"id\":1},{\"title\":\"g\",\"body\":\"h\",\"click_count\":1,\"id\":2}]","results":2}
but in fact is shuld be:
{"rows":[{\"title\":\"ruby\",\"body\":\"goood\",\"click_count\":1,\"id\":1},{\"title\":\"g\",\"body\":\"h\",\"click_count\":1,\"id\":2}],"results":2}
is it a bug in rails?
and now how can to_json generate the expected json data for me?
Thanks!
Sorry,it was my fault.
the action code should be
def index
#posts = Post.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => ({ :results => #posts.size, :rows => #posts.map{|x| x.attributes}).to_json } }
end
end
That is to say: the value of key :rows must be an array object!
Thanks hoooopo!