RAILS 4 to_json include on multiple vars - ruby

I can :include assiciations to json-response using to_json like so:
def stats
#orders = Order.all
respond_to do |format|
format.json { render :json => #orders.to_json(:include => :review) }
end
end
It works okay, but what if I need associations on multiple variables?
This:
def stats
#orders = Order.all
#tasks = Task.all
respond_to do |format|
format.json { render :json => {
orders: #orders.to_json(:include => :review),
tasks: #tasks.to_json(:include => :user)
}
}
end
end
is not working – it's returning a string instead of json:

You can try this. see the following example
e.g.
ActiveSupport::JSON.decode(orders)
To decode the Json string in to Hash.

This is the situation where the jbuilder kicks in, which comes as a default ruby gem in Rails 4

Related

rails update action not working

I have following table in database and also the model created for it.
|id |name |description |created_date |updated_date |
-----------------------------------------------------------------------
|1 |HELLO |greeting |2017-09-28 18:51:51 |2017-09-28 18:51:51|
model.rb
class Person < ApplicationRecord
has_many :person_activities
validates :name, uniqueness: true
end
I want to create update action in controller. It will update the name and description based on the name passed. e.g i want to update the name HELLO to HI. How can i create update action for that?
I tried following update action in controller but it wont hit the update action
def update
byebug
redirect_to Person.find(name: params[:id]).tap { |person|
person.update!(person_params)
}
end
private
def person_params
params.require(:person).permit(:name)
end
routes.rb
resources :person, only: [:index, :show, :create, :update, :destroy], defaults: { format: :json }
Tried testing like this http://localhost:1111/person/HELLO and passing { name: 'HI'} in body params. I am using postman for testing.
You can modify your model, something like this:
class Person< ActiveRecord::Base
before_save :change_name
private
def change_name
self.name="HI" if self.name=="HELLO"
end
end
To answer this properly we would need to understand the logic of how creating a new record with name = "HELLO" would need to be set to "HI". Do you have a lookup table for this logic or is it hardcoded?
The easiest thing I could think of is you can change the value of the passed parameter before doing the update by setting the value of the parameter. E.G.
params["name"] = "HI"
So when you do a person.update it will use the "name" param set to "HI".
Then you could do this in a
def update
respond_to do |format|
params["name"] = "HI"
if #person.update(person_params)
format.html { redirect_to #person, notice: 'Person was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
You could also do the update then just set the value after the update:
def update
respond_to do |format|
if #person.update(person_params)
#person.name = "HI"
#person.save
format.html { redirect_to #person, notice: 'Person was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #person.errors, status: :unprocessable_entity }
end
end
end
From postman you need to call login action first. So it will create a session in postman and then you can call update action.

Ruby Mailer: Wrong number of arguments

I'm working on building out my mailer, but I keep running into:
wrong number of arguments (0 for 1)
Call my crazy, but I feel like I defined everything correctly:
Controller (truncated for brevity):
def create
#cms484 = Cms484.new(cms484_params)
respond_to do |format|
if #cms484.save
SendLink.message(#cms484).deliver_later
format.html { redirect_to cms484s_path, notice: 'Cms484 was successfully created.' }
format.json { render :show, status: :created, location: #cms484 }
else
format.html { render :new }
format.json { render json: #cms484.errors, status: :unprocessable_entity }
end
end
SendLink.rb:
class SendLink < ApplicationMailer
def message(cms484)
#cms484 = cms484
mail(
:subject => 'Hello from Postmark',
:to => #cms484.recipient ,
:from => 'info#mysite.com',
:html_body => '<strong>Hello</strong> user!.',
end
end
Can anybody else see the needle in the haystack or am I missing something else entirely?
I'm using Postmark for delivery if that matters, and have those parameters defined in my application.rb file as per the documentation. Think this is a simpler matter though.
Edit
The complete error:
Completed 500 Internal Server Error in 76ms
ArgumentError (wrong number of arguments (0 for 1)):
app/mailers/send_link.rb:2:in `message'
app/mailers/send_link.rb:4:in `message'
app/controllers/cms484s_controller.rb:38:in `block in create'
app/controllers/cms484s_controller.rb:36:in `create'
I had a similar issue where I named my ActionMailer method "message" it turns out it was a reserved word in Rails and threw an error.
I would assume that "mail" was a reserved word where "email" was not.
mail ... line in SendLink.rb looks wrong , change it to,
mail(
:subject => 'Hello from Postmark',
:to => #cms484.recipient ,
:from => 'info#mysite.com',
:html_body => '<strong>Hello</strong> user!.')
Ok, so I decided to re-write it and behold - it works. Why or what's different than the previous version(other than the method email vs mail, surely that can't be it?), I have no idea. If you can see what it is, Please point it out to me!
Send_link.rb:
class SendLink < ApplicationMailer
def email(cms484)
#cms484 = cms484
mail(
:subject => 'Hello from Postmark',
:to => #cms484.recipient ,
:from => 'info#mysite.com',
)
end
end
Controller:
def create
#cms484 = Cms484.new(cms484_params)
respond_to do |format|
if #cms484.save
SendLink.email(#cms484).deliver_later
format.html { redirect_to cms484s_path, notice: 'Cms484 was successfully created.' }
format.json { render :show, status: :created, location: #cms484 }
else
format.html { render :new }
format.json { render json: #cms484.errors, status: :unprocessable_entity }
end
end
end

Rails 4 function in controller not running

I have some code for a Rails 4 project I'm working on. It uses active_record (mysql2), and there is a has_many :through relationship that works properly when I interact through rails c (in either production or development). When I try to submit the relationship in a form (I am using simple_form), I can't seem to get it to save.
Here is how my information is currently set up (just showing snippets, I can't really show the whole source):
Model:
has_many :categorizations
has_many :resource_categories, through: :categorizations
accepts_nested_attributes_for :resource_categories
accepts_nested_attributes_for :categorizations
Form:
= simple_form_for #resource do |f|
= f.association :resource_categories
Controller:
# POST /resources
# POST /resources.json
def create
#resource = Resource.new(resource_params)
set_categories(#resource, params[:resource][:resource_category_ids])
respond_to do |format|
if #resource.save
format.html {
redirect_to #resource, notice: 'Resource was successfully created.'
}
format.json {
render action: 'show', status: :created, location: #resource
}
else
format.html {
render action: 'new'
}
format.json {
render json: #resource.errors, status: :unprocessable_entity
}
end
end
end
# PATCH/PUT /resources/1
# PATCH/PUT /resources/1.json
def update
respond_to do |format|
if #resource.update(resource_params)
set_categories(#resource, params[:resource][:resource_category_ids])
format.html {
redirect_to #resource, notice: 'Resource was successfully updated.'
}
format.json {
head :no_content
}
else
format.html {
render action: 'edit'
}
format.json {
render json: #resource.errors, status: :unprocessable_entity
}
end
end
end
# Never trust parameters from the scary internet, only allow the white list
# through.
def resource_params
params.require(:resource).permit(
:title, :slug, :ancestry, :status, :author_id, :published, :parent_id,
:resource_category_ids, :preview, :body
)
end
def set_categories(resource, categories)
# Clean out the existing categories (if there are any)
unless resource.resource_categories.blank?
resource.resource_categories.each do |category|
resource.resource_categories.delete(category)
end
end
unless categories.blank?
categories.each do |category|
unless category.blank?
resource.resource_categories << ResourceCategory.find(category)
end
end
end
end
When I issue the following commands using rails c -e production (or just plain rails c) it works (In this example, I assign all categories to all resources):
Resource.all.each do |resource|
ResourceCategory.all.each do |category|
resource.resource_categories << category
end
end
It seems like my problem is that the controller is not calling the helper function
Use this instead:
def create
#resource = Resource.new(resource_params)
#resource.set_categories(params[:resource][:resource_category_ids])
..
end
Move the method in the Resource model:
def set_categories(categories)
# Clean out the existing categories (if there are any)
unless new_record?
unless resource_categories.blank?
resource_categories.each do |category|
resource_categories.delete(category)
end
end
end
unless categories.blank?
categories.each do |category|
unless category.blank?
resource_categories << ResourceCategory.find(category)
end
end
end
end
#resource is instance variable of your Controller, you don't need to pass it to a method. Perform all your operations directly on the instance variable.
OP still had problem while saving the record, changed :resource_category_ids to :resource_category_ids => [] in resource_params method:
def resource_params
params.require(:resource).permit(
:title, :slug, :ancestry, :status, :author_id, :published, :parent_id,
:preview, :body, :resource_category_ids => []
)
end

How to download search results of index page using axlsx?

First, I am really sorry if this question is too trivial. I am new with rails and couldn't figure out where i am doing it wrong.
I have a model named Costing and in it's index page i have a search form. I am trying to use 'axlsx' gem to download only the search results but I always get all the rows. I am also using 'will_paginate' gem.
Here is my code.
//costings_controller.rb
def index
#costings = Costing.search(params[:search] , params[:page])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #costings }
format.xlsx {
send_data #costings.to_xlsx.to_stream.read, :filename => 'costings.xlsx', :type => "application/vnd.openxmlformates-officedocument.spreadsheetml.sheet"
}
end
end
// index.html.erb
<%= link_to 'Download Costings', url_for(:format=>"xlsx") %>
Please help me here.
Thanks a lot in advance.
Here is the code that I made for a demo of axlsx gem. Browse through it and implement your requirement in the controller. Here is the output of this demo.
//costings_controller.rb
def download
#costings = Costing.search(params[:search] , params[:page])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #costings }
format.xlsx {
send_data #costings.to_xlsx.to_stream.read, :filename => 'costings.xlsx', :type => "application/vnd.openxmlformates-officedocument.spreadsheetml.sheet"
}
end
end
// index.html.erb
<%= form_for :costing, url: download_costing_index_path do %>
...
<% end %>
//routes
resources :costing do
collection do
post :download, :defaults => { :format => 'xlsx' }
end
end

Why does this rescue syntax work?

Ok so I have this method of an application I am working with and it works in production. My question why does this work? Is this new Ruby syntax?
def edit
load_elements(current_user) unless current_user.role?(:admin)
respond_to do |format|
format.json { render :json => #user }
format.xml { render :xml => #user }
format.html
end
rescue ActiveRecord::RecordNotFound
respond_to_not_found(:json, :xml, :html)
end
rescues do not need to be tied to an explicit begin when they're in a method, that's just the way the syntax is defined. For examples, see #19 here and this SO question, as well as the dupe above.
rescue can work alone . no need of begin and end always .
You can use rescue in its single line form to return a value when other things on the line go awry:
h = { :age => 10 }
h[:name].downcase # ERROR
h[:name].downcase rescue "No name"
rescue word is part of method definition
But in controllers better to rescue errors with rescue_from
try this
def edit
begin
load_elements(current_user) unless current_user.role?(:admin)
respond_to do |format|
format.json { render :json => #user }
format.xml { render :xml => #user }
format.html
end
rescue ActiveRecord::RecordNotFound
respond_to_not_found(:json, :xml, :html)
end
end

Resources