render :partial not working as expected - ruby-on-rails-4

In my index view of products, I have an "Add to cart" that calls javascript function addToCart:
addToCart: function() {
$.ajax({type: 'GET',
url: 'store/add_to_cart/2', // fixed id of product
timeout: 5000,
success: function() { alert('Added !'); },
error: function() { alert('Error !'); }
});
}
def add_to_cart // not working
begin
prod = Product.find(params[:id])
#cart = find_cart
#cart.add_product(prod)
render :partial => 'cart', :object => #cart if request.xhr?
end
end
With this add_to_cart, it renders the partial but also renders the default view for this method - add_to_cart.html.haml -
But if I do it like the following, it renders only the partial.
Could anybody explain me why it is different?
def add_to_cart // working fine
begin
prod = Product.find(params[:id])
#cart = find_cart
#cart.add_product(prod)
if request.xhr?
render :partial => 'cart', :object => #cart
else
redirect_to_index
end
end
end
Thanks for your help !!

The problem is that in that line rails get's confused where are the params for the render call and where is the statement.
You should probably try going like render(:partial => 'cart', :object => #cart) if request.xhr?.
And another thing. If you're using a local variable in the partial, it's better to use locals: {cart: #cart} instead of your :object. Or, if you are following the conventions and that cart partial is in app/view/carts/_cart.html* you can just say render #cart.

Related

How to render custom form inside a custom block programmatically with drupal 8?

I need render a custom form in a custom block programmatically. This is my code inside a controller:
$form = \Drupal::formBuilder()->getForm('Drupal\wa_encuesta\Form\NewForm', $extra);
[enter image description here][1] $form=render($form);
$blockContent = BlockContent::create([
'info' => $title,
'type' => 'basic',
'body'=>[
'value' => $form,
'format' => 'full_html'
]
]);
$blockContent->save();
//$block = Block::create([
$block = \Drupal\block\Entity\Block::create([
'id' => 'about_us',
'plugin' => 'block_content:' . $blockContent->uuid(),
'region' => 'header',
'provider' => 'block_content',
'weight' => -100,
'theme' => \Drupal::config('system.theme')->get('default'),
'visibility' => array(),
'settings' => [
'label' => 'About us',
'label_display' => FALSE,
],
]);
$block->save();
The form render a custom block but this not working when submit.
I usually get this done by combination of hook_preprocess_block or hook_preprocess_node and twig file.
Example:
Say, you want to render this in a block:
Define hook_preprocess_block() in your theme file:
function THEME_preprocess_block(&$variables) {
$blockId = $variables['elements'][#id];
//check for your block id
$render_service = Drupal::service('renderer');
$form_html = $render_service->renderPlain(Drupal\wa_encuesta\Form\NewForm::class, $extra);
//set in variables
$variables['my_form_html'] = $form_html;
}
Now, identify your twig file name for your block, and just put:
{{ my_form_html }}
please see my answer to the same question here: How to create a form using block module in drupal 8?
Basically you just create a separate form and a block, render the form in the block and then place the block in the desired region.

passing an id in Rails 4

If i start this question by showing you my routes: -
c:\Sites\work\easygifts>rake routes
Prefix Verb URI Pattern Controller#Action
writing_stores GET /stores/writing(.:format) stores#writing
office_stores GET /stores/office(.:format) stores#office
time_stores GET /stores/time(.:format) stores#time
home_stores GET /stores/home(.:format) stores#home
wellness_stores GET /stores/wellness(.:format) stores#wellness
travel_stores GET /stores/travel(.:format) stores#travel
bags_stores GET /stores/bags(.:format) stores#bags
leisure_stores GET /stores/leisure(.:format) stores#leisure
quote_stores GET /stores/quote(.:format) stores#quote
stores GET /stores(.:format) stores#index
POST /stores(.:format) stores#create
new_store GET /stores/new(.:format) stores#new
edit_store GET /stores/:id/edit(.:format) stores#edit
store GET /stores/:id(.:format) stores#show
PATCH /stores/:id(.:format) stores#update
PUT /stores/:id(.:format) stores#update
DELETE /stores/:id(.:format) stores#destroy
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:id/edit(.:format) products#edit
product GET /products/:id(.:format) products#show
PATCH /products/:id(.:format) products#update
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
root GET / stores#index
The issue i am having is getting the :id into the 'quote' view.
I am wanting to see in my routes; quote_stores GET /stores/quote/:id(.:format) stores#quote Or something like it.
Can :id only be passed through CRUD?? I thought i could pass instance variables through pretty much anywhere so I wrote this in my view as the link to the view with the :id info passed into it.
<% #products.each do |office| %>
<div class="item">
<%= link_to image_tag(office.image_url), image_path(office.image_url), class: 'fancybox' %>
<p><strong><%= office.item_code%></strong>
</br><em><%= truncate(office.title, length: 18) %></em></p>
<p class="showArticle"><%= link_to 'Show Article', store_path(office) %></p>
<p class="addTo"><%= link_to 'Price Info', quote_stores_path(office) %></p>
</div>
<% end %>
I am referring to the <%= link_to 'Price Info', quote_stores_path(office) %> which upon click takes you to the correct view and in the URI path it even lists the correct :id however it does not pass into the view that :id's information.
My controller code is as follows: -
class StoresController < ApplicationController
add_breadcrumb 'home', :stores_path
def index
#products = Product.all
end
def show
#products = Product.find(params[:id])
if #products.nil?
redirect_to action: :index
end
add_breadcrumb 'Back', #products.section
end
def writing
#products = Product.where(:section => 'writing').paginate(:per_page => 5, :page => params[:page])
add_breadcrumb 'writing', writing_stores_path
end
def office
#products = Product.where(:section => 'office').paginate(:per_page => 5, :page => params[:page])
add_breadcrumb 'office', office_stores_path
end
def time
#products = Product.where(:section => 'time').paginate(:per_page => 5, :page => params[:page])
add_breadcrumb 'time', time_stores_path
end
def home
#products = Product.where(:section => 'home').paginate(:per_page => 5, :page => params[:page])
add_breadcrumb 'home', home_stores_path
end
def wellness
#products = Product.where(:section => 'wellness').paginate(:per_page => 5, :page => params[:page])
add_breadcrumb 'wellness', wellness_stores_path
end
def travel
#products = Product.where(:section => 'travel').paginate(:per_page => 5, :page => params[:page])
add_breadcrumb 'travel', travel_stores_path
end
def bags
#products = Product.where(:section => 'bags').paginate(:per_page => 5, :page => params[:page])
add_breadcrumb 'bags', bags_stores_path
end
def leisure
#products = Product.where(:section => 'leisure').paginate(:per_page => 5, :page => params[:page])
add_breadcrumb 'leisure', leisure_stores_path
end
def quote
#products = Product.find_by(params[:id])
if #products.nil?
redirect_to action: :index
end
end
end
So apart from my code not being DRY, what am i missing here please? What am i not understanding about :id's?
In your config/routes.rb, you probably have this line:
resources :stores
Which creates routes for the standard CRUD actions of the stores resource. You can define additional actions for this resource which either apply to the collection (multiple products) or the members individually (a single product).
Please note that it would probably more logical to name the resource products rather than stores, since it seems to be handling Products.
In your case, you'd want to define an additional member action. Since it applies to a single product, Rails will define a route which takes an id parameter:
resources :stores do
member do
get 'quote'
end
end
This will generate the following route (rake routes):
quote_store GET /stores/:id/quote(.:format) stores#quote
Note that the route is called quote_store, the singular form rather than the plural.
Also see the Rails guides for more information about collection and member routes.

How can I return a 404 JSON format in Rails 4?

I am new to Ruby. I am writing a Restful API application using Rails 4.
How can I return a 404 JSON not found string when the record is not found?
I found a number of posts but no luck, only for Rails 3.
In my controller I can caught the exception
def show
country = Country.find(params[:id])
render :json => country.to_record
rescue Exception
render :json => "404"
end
But I want a generic one to capture all the not found resources.
Use rescue_from. See http://guides.rubyonrails.org/v2.3.11/action_controller_overview.html#rescue
In this instance use something like:
class ApplicationController < ActionController::Base
rescue_from ActiveRecord::RecordNotFound, :with => :record_not_found
private
def record_not_found(error)
render json: { error: error.message }, status: :not_found
end
end
Do:
def show
country = Country.find(params[:id])
render :json => country.to_record
rescue Exception
render :json => 404_json_text, :status => 404
end

Full Calendar and auto Filtering Events Rails 4

I am building a calendar application which requires certain events to display on the calendar based on the location that is being viewed. I have full calendar working in which it displays ALL the events in the database. I am trying to achieve an auto filter to only show the events that pertain to the location being viewed.
Current Setup (My Events Model is called "Campaigns" to align with my application)
Campaign Controller
def index
#campaigns = Campaign.all
#campaigns = #campaigns.after(params['start']) if (params['start'])
#campaigns = #campaigns.before(params['end']) if (params['end'])
respond_to do |format|
format.html # index.html.erb
format.json { render json: #campaigns }
end
end
Campaign Model
belongs_to :location
scope :before, lambda {|end_time| {:conditions => ["ends_at < ?", Campaign.format_date(end_time)] }}
scope :after, lambda {|start_time| {:conditions => ["starts_at > ?", Campaign.format_date(start_time)] }}
# need to override the json view to return what full_calendar is expecting.
# http://arshaw.com/fullcalendar/docs/event_data/Event_Object/
def as_json(options = {})
{
:id => self.id,
:title => self.name,
:description => "",
:start => starts_at.rfc822,
:end => ends_at.rfc822,
:allDay => false,
:recurring => false,
:url => Rails.application.routes.url_helpers.campaign_path(friendly_id)
}
end
def self.format_date(date_time)
Time.at(date_time.to_i).to_formatted_s(:db)
end
Script inside "Location" show.html.erb
$(document).ready(function() {
var date = new Date();
var d = date.getDate();
var m = date.getMonth();
var y = date.getFullYear();
$('#calendar').fullCalendar({
editable: true,
header: {
left: 'prev,next today',
center: 'title',
right: 'month,agendaWeek,agendaDay'
},
defaultView: 'month',
loading: function(bool){
if (bool)
$('#loading').show();
else
$('#loading').hide();
},
// a future calendar might have many sources.
eventSources: [{
url: '/campaigns',
data: { <%= #locations %> }, #added but not filtering as I had hoped
color: 'blue',
textColor: 'white',
ignoreTimezone: false
}],
timeFormat: 'h:mm t{ - h:mm t} ',
dragOpacity: "0.5",
});
});
Currently I am able to achieve in displaying the campaigns that belong to the given location on the display side in the location show with:
<strong>Campaigns:</strong>
<%= render partial: #campaigns %>
</p>
And then in the location controller
def show
#campaigns = #location.campaigns
end
I have tried for hours to figure this out with no luck in getting the same result to the calendar. Can someone please help me in figuring out what is required to filter the "Campaigns" that pertain to the viewing location??
Thanks!
Have you tried this ?
eventSources: [{
url: '/campaigns',
data: { 'location': <%= #locations %> }, <- try this like so
color: 'blue',
textColor: 'white',
ignoreTimezone: false
}],

Username in URL using Regex & Route

I have a method in my Users Controller called view, which should display a specified (by URL) user:
public function view($username = null) {
$this->User->username = $username;
if (!$this->User->exists()) {
throw new NotFoundException('Няма такъв потребител!');
}
if (!$username) {
$this->Session->setFlash('Няма такъв потребител!');
$this->redirect(array('action' => 'index'));
}
$this->set('user', $this->User->read());
}
And in the route config:
Router::connect('/:username', array('controller' => 'users', 'action'=> 'view'), array('username' => '^([a-z0-9])+$'));
But when I try: www.example.com/Username it returns a fatal error: Missing controller.
I tried also this:
Router::connect('/users/:username', array('controller' => 'users', 'action'=> 'view'), array('pass' => array('username'), 'username' => '^([a-z0-9])+$'));
Unfortunately for this sort of setup using /:username is too simple, it will pretty much override every single other route. To do this effectively ( + the proper CakePHP way) you need to setup a custom route, here is mine which pretty much achieves the same thing. Just replace "product" with "user" for most cases, read through it though, to make sure you understand what's going on..
Look at my routes config as well if you still can't work it out.
If you want to route /user/dunhamzz to a profile you would set it up like this:
Router::connect('/user/:username',
array('controller' => 'users', 'action' => 'view'),
array('pass' => array('username')
);
Then your view action simply gets the username as the first argument:
public function view($username) {
}