How to render view in parent controller - ruby-on-rails

I want to pass down values from a parent controller, to the views of the child, or ideally, render the view directly from the parent controller.
Here is my parent controller:
class SuperBlogPostsController < ApplicationController
def index(country)
if country == "AUSTRALIA"
#posts = AustraliaBlogPost.all
hash = { posts: #posts, featured_post: AustraliaBlogPost.find_by(featured_post: true) }
respond_to do |format|
format.html {render 'super_blog_post/index'}
format.json {render json: hash}
end
end
end
def show(country)
if country == "AUSTRALIA"
#post = AustraliaBlogPost.find(params[:id])
respond_to do |format|
format.html {render 'super_blog_post/show'}
format.json {render json: #post}
end
end
end
And here is my child:
class AustraliaBlogPostsController < SuperBlogPostsController
def index
super(country: 'AUSTRALIA')
end
def show
super(country: 'AUSTRALIA')
end
end
This is the error that I get, even when I append .json at the end of the url:
Is it possible to do the rendering of the view in the parent, or at least pass down the return values of the variables generated by the parent to the child? If I've been unclear at all, let me know!
Thanks!

Your parent controller methods accept a normal parameter, not named parameter.
Instead of:
super(country: 'AUSTRALIA')
You need
super('AUSTRALIA')
But I must say, the entire logic of your controllers doesn't make a lot of sense.

Related

How to avoid create some attribute in controller's create method?

I have a model like this:
class Url < ApplicationRecord
validates ...
before_create :generate_number
def generate_number
self.number = a random value
end
end
and a create() method in controller:
def create
#url = Url.new(url_params)
respond_to do |format|
if #url.save
format.html { redirect_to #url, notice: 'Url was successfully created.' }
format.json { render :show, status: :created, location: #url }
else
format.html { render :new }
format.json { render json: #url.errors, status: :unprocessable_entity }
end
end
end
My DB only have two fields: given_url and number. Now, when I go to the new page, there's 2 input form for given_url and number. But I want number take the value from generate_number, not from the form. How can I do that?
Or more specific, is there a way to make the generate_number method to overrides user's input after the app already receive value from user's input?
You can simply restrict the input from user by using strong params
def url_params
params.require(:url).permit(:other, :params)
end
Well, I have found a way to fix this. As #ts mentioned in the question's comment, I changed before_create :generate_number to after_create :generate_number and added self.save to the end of generate_number method:
def generate_number
...
self.number = some number
self.save
end

"param is missing or the value is empty: color" error in controller

I followed a tutorial on YouTube involving making a simple model, printing out the results and updating the model with a form and did a find and replace for what I was trying to accomplish ("text files, the tutorial involved images)
Everything worked up until around the time I just wanted an single index page and tried merging all the controller logic into the index.
I'm currently getting an error reading param is missing or the value is empty: color on params.require in the controller below.
class ColorsController < ApplicationController
before_action :find_color, only: [:destroy]
def index
#colors = Color.all.order("created_at DESC")
#color = Color.new(color_params)
end
def destroy
#color.destroy
end
private
def find_color
#color = Color.find(params[:id])
end
def color_params
params.require(:color).permit(:file)
end
end
What I take from this is that it's not recognizing the #color instance variable, but I don't know or why I'm supposed to rectify this.
Model:
class Color < ActiveRecord::Base
has_attached_file :file
validates_attachment_content_type :file, :content_type => ["application/xml"]
end
Form:
= simple_form_for #color do |f|
= f.input :file
= f.submit
Explanation of what I'm doing wrong is much appreciated.
param is missing or the value is empty: color
You should change your index method to below
def index
#colors = Color.all.order("created_at DESC")
#color = Color.new #notice the change here
end
Also, you should define a create method like below
def create
#color = Color.new(color_params)
respond_to do |format|
if #color.save
format.html { redirect_to #color, notice: 'Color was successfully created.' }
format.json { render :show, status: :created, location: #color }
else
format.html { render :new }
format.json { render json: #color.errors, status: :unprocessable_entity }
end
end
end

Rails - Combining scopes

Here is the index method of my People Controller
def index
#people_without_pagination = Person
.for_branch(session[:branch_id])
.for_interests(params[:interest_search])
.search_query(params[:search_term])
.for_lead_sources(params[:lead_source_search])
.for_labels(params[:label_list_search])
#people = Person
.for_branch(session[:branch_id])
.for_interests(params[:interest_search])
.search_query(params[:search_term])
.for_lead_sources(params[:lead_source_search])
.for_labels(params[:label_list_search])
.page params[:page]
if(params[:my_contacts]=="true")
#people.my_contacts(current_user.id)
#people_without_pagination.my_contacts(current_user.id)
end
get_facets
#organization = Organization.find(session[:organization_id])
respond_to do |format|
format.html
format.json {render partial: 'table.html', locals: { people: #people, organization: #organization, facets: #facets}}
format.csv { send_data #people_without_pagination.to_csv}
end
end
As you can see, the my_contacts scope is only to be used when the param "my_contacts" is set to true.
However, it never seems to be applied when I split the scopes. When I combine the my_contacts scope with the rest, it works perfectly. Code here :
def index
#people_without_pagination = Person
.for_branch(session[:branch_id])
.for_interests(params[:interest_search])
.search_query(params[:search_term])
.for_lead_sources(params[:lead_source_search])
.for_labels(params[:label_list_search])
.my_contacts(current_user.id)
#people = Person
.for_branch(session[:branch_id])
.for_interests(params[:interest_search])
.search_query(params[:search_term])
.for_lead_sources(params[:lead_source_search])
.for_labels(params[:label_list_search])
.page(params[:page])
.my_contacts(current_user.id)
get_facets
#organization = Organization.find(session[:organization_id])
respond_to do |format|
format.html
format.json {render partial: 'table.html', locals: { people: #people, organization: #organization, facets: #facets}}
format.csv { send_data #people_without_pagination.to_csv}
end
end
Is this not an acceptable way of combining scopes?
Each time you call the relation builder methods (where, joins, etc.) or your model's scopes you create a fresh new scope - it doesn't mutate the existing scope. So
#people.my_contacts(current_user.id)
Creates a new scope but then throws it away, leaving #people unchanged. You should be doing
#people = #people.my_contacts(current_user.id)
This also means that your code could be simpler:
#people_without_pagination = Person.
... #your scopes here
#people = #people_without_pagination.page(params[:page])
rather than repeating that list of scopes.

Rails - How to render json with extra field in index controller method

I'm using Rails 4.0.2 with paperclip for image upload in my project. Also I need to send a full image path of paperclip. So I can do it with add new field and set image path manually in my show controller method for particular record.
show
def show
respond_to do |format|
format.html
format.json { :json => JSON::parse(#demo.to_json.merge("new_field" => #demo.image_url.url).to_json}
end
end
When I view Json for any of my record, this is will showing good.
{
id: "1",
name: "demo",
new_field: "/demo/1/original/file.jpg"
}
In same scenario, I need to get the full image path of paperclip image for all records when I am requesting to index method on controller
index
def index
#demos = Demo.all
respond_to do |format|
format.html
format.json { :json => Demo.all.to_json}
end
end
I tried some of codes, but I don't know how exactly to write
def index
#demos = Demo.all
#demos.each do |demo|
new_field = {"new_field" => #demo.image_url.url}
# After I stucked with logic, how to uppend with 'demo'.
end
respond_to do |format|
format.html
format.json { :json => Demo.all.to_json}
end
end
How do I iterate my individual Demo model and How to merge full image path into each record.
I found the solution for my question,
def index
#demos = Demo.all
#demos_data = []
#demos.each do |demo|
new_field = {"new_field" => #demo.new_field.url}
demo = JSON::parse(demo.to_json).merge(new_field)
#demos_data << demo
end
respond_to do |format|
format.html
format.json { :json => #demos_data}
end
end
I suggest you to use two approaches, 1)use active model serializer to expose json response. 2) use jbuilder library to expose custom fields. Still you need help please let me know.
Try this:-
def index
#demos = Demo.all
#demos_data = []
#demos.each do |demo|
demo["new_field"] = #demo.image_url.url
#demos_data << demo
end
respond_to do |format|
format.html
format.json { :json => #demos_data}
end
end
maybe you can try:
def index
#demos = Demo.all
#demos.map do |demo|
new_field = {"new_field" => #demo.image_url.url}
demo.attributes.merge(new_field)
end
respond_to do |format|
format.html
format.json { :json => #demos}
end
end
attributes method returns a hash of all the object attributes, just need merge new key-value into the returned hash.
Another way of doing it is in your controller where you are rendering the json
render json: #merchants,
include: {
offers: {
except: [:created_at, :updated_at],
include: {
categories: {
except: [:created_at, :updated_at]
}
}
},
location: {
methods: :country_name,
except: [:created_at, :updated_at]
}
},
except: [:created_at, :updated_at]
Note the methods: :country_name, there you can render methods from your model as json attributes. and through include: ... you can eager load and render related models.

How to render view from of a different controller?

In my project I have two controllers called PropertiesController and FacilitiesController. After creating a property in PropertiesController, I want to load the view(form) from FacilitiesController.
I tried to do using render facilities/new which shows an error(First argument in form cannot contain nil or be empty), as I have not initialized the argument(#facility) passed to form_for method.
I can avoid the above error by initializing the #facility variable in PropertiesController. But I have code in the form_for which calls method on the object present in FacilitiesController. I don't want all that code to be duplicated again in PropertiesController.
How should I render the view from FacilitiesController without duplicating the code?
I hope below code work for you
class PropertiesController < ApplicationController
def create
#property = Property.new(property_params)
respond_to do |format|
if #property.save
format.html { redirect_to facility_new_path, notice: 'Property was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: #property.errors, status: :unprocessable_entity }
end
end
end
end

Resources