How to use Spree's Authentication in form - ruby-on-rails

i am learning rails and creating a web app which also got ecommerce in it
There is a Form which user can fill only if he is logged in, For that i was using Devise, then for e-commerce i installed Spree
Spree got its own login authentication, and there is no authenticate_user! in controllers too,
i removed devise and having a tough time finding how to use Spree's authentication with my Form
here is UPDATED Form's controller:
complaints_controller.rb
module Spree
class ComplaintsController < Spree::StoreController
before_action :require_login
before_action :set_complaint, only: [:show, :edit, :update, :destroy]
# GET /complaints
# GET /complaints.json
def require_login
redirect_to spree_login_path unless current_spree_user
end
def index
#complaints = Complaint.all
end
# GET /complaints/1
# GET /complaints/1.json
def show
end
# GET /complaints/new
def new
#complaint = Complaint.new
end
# GET /complaints/1/edit
def edit
end
# POST /complaints
# POST /complaints.json
def create
#complaint = Complaint.new(complaint_params)
respond_to do |format|
if #complaint.save
format.html { redirect_to #complaint, notice: 'Complaint was successfully created.' }
format.json { render :show, status: :created, location: #complaint }
else
format.html { render :new }
format.json { render json: #complaint.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /complaints/1
# PATCH/PUT /complaints/1.json
def update
respond_to do |format|
if #complaint.update(complaint_params)
format.html { redirect_to #complaint, notice: 'Complaint was successfully updated.' }
format.json { render :show, status: :ok, location: #complaint }
else
format.html { render :edit }
format.json { render json: #complaint.errors, status: :unprocessable_entity }
end
end
end
# DELETE /complaints/1
# DELETE /complaints/1.json
def destroy
#complaint.destroy
respond_to do |format|
format.html { redirect_to complaints_url, notice: 'Complaint was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_complaint
#complaint = Complaint.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def complaint_params
params.require(:complaint).permit(:id_society, :id_user, :heading, :text, :active, :action, :IsDelete, :flat_number)
end
end
end
<% end %>
index.html.erb
<% if spree_current_user %>
<p id="notice"><%= notice %></p>
<h1>Listing Complaints</h1>
<table>
<thead>
<tr>
<th>Id society</th>
<th>Id user</th>
<th>Heading</th>
<th>Text</th>
<th>Active</th>
<th>Action</th>
<th>Isdelete</th>
<th>Flat number</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #complaints.each do |complaint| %>
<tr>
<td><%= complaint.id_society %></td>
<td><%= complaint.id_user %></td>
<td><%= complaint.heading %></td>
<td><%= complaint.text %></td>
<td><%= complaint.active %></td>
<td><%= complaint.action %></td>
<td><%= complaint.IsDelete %></td>
<td><%= complaint.flat_number %></td>
<td><%= link_to 'Show', complaint %></td>
<td><%= link_to 'Edit', edit_complaint_path(complaint) %></td>
<td><%= link_to 'Destroy', complaint, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Complaint', new_complaint_path %>
<% else %>
<h1> please login</h1>
<% end %>
This works, as it verifies user's authentication in View, is there any way to check it in controller? Like if user is logged in it will be sent to action or else redirected to login?
Thank you

Spree uses devise authentication through a extension:
https://github.com/spree/spree_auth_devise
For authenticate your actions at controller(your own controllers) level, you need to define your own authentication filter. So you can manage something like this:
before_action :require_login
def require_login
redirect_to login_url unless current_spree_user
end

Related

Rails - NoMethodError even though method is defined

So my goal with this method is to have it link to customers/1/showcar similar to how it will link to customers/1/edit, which is how I'm attempting to model my code.
My controller is
class CustomersController < ApplicationController
before_action :set_customer, only: [:show, :edit, :update, :destroy, :showcar]
# GET /customers
# GET /customers.json
def index
#customers = Customer.all
end
# GET /customers/1
# GET /customers/1.json
def show
end
# GET /customers/1/showcar
def showcar
end
# GET /customers/new
def new
#customer = Customer.new
end
# GET /customers/1/edit
def edit
end
# POST /customers
# POST /customers.json
def create
#customer = Customer.new(customer_params)
respond_to do |format|
if #customer.save
format.html { redirect_to #customer, notice: 'Customer was successfully created.' }
format.json { render :show, status: :created, location: #customer }
else
format.html { render :new }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /customers/1
# PATCH/PUT /customers/1.json
def update
respond_to do |format|
if #customer.update(customer_params)
format.html { redirect_to #customer, notice: 'Customer was successfully updated.' }
format.json { render :show, status: :ok, location: #customer }
else
format.html { render :edit }
format.json { render json: #customer.errors, status: :unprocessable_entity }
end
end
end
# DELETE /customers/1
# DELETE /customers/1.json
def destroy
#customer.destroy
respond_to do |format|
format.html { redirect_to customers_url, notice: 'Customer was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_customer
#customer = Customer.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def customer_params
params.require(:customer).permit(:cust_id, :cust_fname, :cust_lname, :cust_phone, :cust_addr, :cust_date)
end
end
and my html.erb file where I'm attempting to call the method is
<style>
th, td{
padding-left: 20px;
}
</style>
<p id="notice"><%= notice %></p>
<h1>Customers</h1>
<table>
<thead>
<tr>
<th>Cust ID</th>
<th>Cust fname</th>
<th>Cust lname</th>
<th>Cust phone</th>
<th>Cust addr</th>
<th>Cust date</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #customers.each do |customer| %>
<% belongstocust = Car.where(cust_id: customer.cust_id) %>
<tr>
<td><%= customer.cust_id %></td>
<td><%= customer.cust_fname %></td>
<td><%= customer.cust_lname %></td>
<td><%= customer.cust_phone %></td>
<td><%= customer.cust_addr %></td>
<td><%= customer.cust_date %></td>
<td><%= link_to 'Show', customer %></td>
<td><%= link_to 'Edit', edit_customer_path(customer) %></td>
<td><%= link_to 'Destroy', customer, method: :delete, data: { confirm: 'Are you sure?' } %></td>
#placeholder, not permanent code
<% i = '' %>
<% belongstocust.each do |car| %>
<% i = car.car_model %>
<td><%= link_to 'Show ' + i, car_path(car) %></td>
<% end %>
<td><%= link_to 'Show Car', showcar_customer_path(customer) %> </td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Customer', new_customer_path %>
<br>
<%= link_to 'Home', home_index_path %>
The issue is, whenever I have the code <td><%= link_to 'Show Car', showcar_customer_path(customer) %> </td>, I get the noMethodError even though the method is defined inside the controller, and it looks the exact same as def show and def edit. I've tried making a controller called customer, and adding the showcar method to that controller, and it worked, but it wouldn't pass over the customer. I also tried adding showcar to customer.rb, but it also gave me a noMethodError. I'm a complete noob when it comes to ruby, and was just told to make a project using the framework, so I've been having to learn along the way. This could be a really simple issue that I don't know how to solve due to my ignorance, so if that's the case I'm sorry.
I get the noMethodError even though the method is defined inside the controller
No. You have showcar defined, not showcar_customer_path. You are missing a route, the thing that defines xxx_path methods.
In your config/routes.rb you probably have
resources :customers
To register this new action, you can do
resources :customers do
member do
get :showcar
end
end
Now showcar_customer_path should be available to use in the views.

Make a simple method work in view

REFORMULATED FOR MORE INFO
I'll be rather short. As a newbie, that's the error I am getting while developing my rails app:
param is missing or the value is empty: task
The error highlights:
def task_params
params.require(:task).permit(:name, :description, :deadline, :status, :pdf, :done)
end
It happens when I click the button 'Mark as done' I'm creating.
Here follows the code:
app/views/tasks/index.html.erb:
<p id="notice"><%= notice %></p>
<h1>Tasks</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Time</th>
<th>Ready?</th>
<th colspan="10"></th>
</tr>
</thead>
<tbody>
<% #tasks.each do |task| %>
<tr>
<td><%= task.name %></td>
<td><%= task.description %></td>
.
.
.
<td><%= (link_to 'Mark done', task_path(task, done: true), method: :PUT) %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
app/controllers/tasks_controller.rb:
class TasksController < ApplicationController
before_action :set_task, only: [:show, :edit, :update, :destroy]
# GET /tasks
# GET /tasks.json
def index
#tasks = Task.all
end
# GET /tasks/1
# GET /tasks/1.json
def show
end
# GET /tasks/new
def new
#task = Task.new
end
# GET /tasks/1/edit
def edit
end
# POST /tasks
# POST /tasks.json
def create
#task = Task.new(task_params)
respond_to do |format|
if #task.save
format.html { redirect_to #task, notice: 'Task was successfully created.' }
format.json { render :show, status: :created, location: #task }
else
format.html { render :new }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /tasks/1
# PATCH/PUT /tasks/1.json
def update
respond_to do |format|
if #task.update(task_params)
format.html { redirect_to #task, notice: 'Task was successfully updated.' }
format.json { render :show, status: :ok, location: #task }
else
format.html { render :edit }
format.json { render json: #task.errors, status: :unprocessable_entity }
end
end
end
# DELETE /tasks/1
# DELETE /tasks/1.json
def destroy
#task.destroy
respond_to do |format|
format.html { redirect_to tasks_url, notice: 'Task was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_task
#task = Task.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def task_params
params.require(:task).permit(:name, :description, :deadline, :status, :pdf, :done)
end
end
Thanks for the help!
since you've done this in controller as you said in command
before_action :set_task
def set_task
#task = Task.find(params[:id)
end
you should simply be able to do :
<td><%= 'Mark as done', tasks_setdone_path(task), method: :post %></td>
and not <td><%= 'Mark as done', tasks_setdone_path(task), method: :post %></td>
'#' represent instance variable accessible from controller AND template.
Another thing is that your action controller will require a respond (html or json).
Now that you answer is given, here is the proper way to do it.
task_path(#task, done: true), method: :PUT
POST is use for creation where PUT is use for updating an object.

Faraday::ConnectionFailed, Connection refused - connect(2) for “localhost” port 9200 Error Ruby on Rails

I am trying to add Searchkick gem in my app with Ruby on Rails but when i type a word in my search box i get this error in my app. I have installed elasticsearch and the latest version of java as required but still the error is the same. This is the error i am getting :
Faraday::ConnectionFailed in PostsController#search
Connection refused - connect(2) for "localhost" port 9200
Here's my code:
The Terminal shows that elastic search is installed:
Terminal
Warning: elasticsearch-1.7.3 already installed
posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]
def search
if params[:search].present?
#posts = Post.search(params[:search])
else
#posts = Post.all
end
end
# GET /posts
# GET /posts.json
def index
#posts = Post.all
end
# GET /posts/1
# GET /posts/1.json
def show
end
# GET /posts/new
def new
#post = Post.new
end
# GET /posts/1/edit
def edit
end
# POST /posts
# POST /posts.json
def create
#post = Post.new(post_params)
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render :show, status: :created, location: #post }
else
format.html { render :new }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
respond_to do |format|
if #post.update(post_params)
format.html { redirect_to #post, notice: 'Post was successfully updated.' }
format.json { render :show, status: :ok, location: #post }
else
format.html { render :edit }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
# DELETE /posts/1
# DELETE /posts/1.json
def destroy
#post.destroy
respond_to do |format|
format.html { redirect_to posts_url, notice: 'Post was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_post
#post = Post.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def post_params
params.require(:post).permit(:name)
end
end
model/post.rb
class Post < ActiveRecord::Base
searchkick
end
views/post/index.html.erb
<p id="notice"><%= notice %></p>
<%= form_tag search_posts_path, method: :get, class: "navbar-form navbar-right", role: "search" do %>
<p>
<%= text_field_tag :search, params[:search], class: "form-control" %>
<%= submit_tag "Search", name: nil, class: "btn btn-default" %>
</p>
<% end %>
<h1>Listing Posts</h1>
<table>
<thead>
<tr>
<th>Name</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Post', new_post_path %>
views/search.html.erb
<table>
<thead>
<tr>
<th>Search Result</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #posts.each do |post| %>
<tr>
<td><%= post.name %></td>
<td><%= link_to 'Show', post %></td>
<td><%= link_to 'Edit', edit_post_path(post) %></td>
<td><%= link_to 'Destroy', post, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
config/routes.rb
Rails.application.routes.draw do
resources :posts do
collection do
get 'search'
end
end
end
This is the screen i am getting with the error shown :
Connection refused - connect(2) for "localhost" port 9200
Looks like your elastic search service is not running. You have to make sure it's running.
To see if your elastic search service is running, run:
curl localhost:9200
If it's running, then it should return a hash like this:
{
"status" : 200,
"name" : "Buzz",
"cluster_name" : "your_cluster_name",
"version" : {
"number" : "1.4.5",
"build_hash" : "...",
"build_timestamp" : "2015-04-27T08:06:06Z",
"build_snapshot" : false,
"lucene_version" : "4.10.4"
},
"tagline" : "You Know, for Search"
}
If elastic search is not running which is most likely the case for you, start it using this command:
sudo service elasticsearch start
That should fix your problem.

How to do recurring event using fullCalendar in ruby on rails

Hi I need to create recurring event in rails. i.e) every monday i want to conduct meeting for 6months. so i want to make this event as recurrance event in calendar.as I am new to rails, i have followed some links. but i dont get any code or idea about how to do it. I have searched well in SO and got one link.
http://stackoverflow.com/questions/10148960/recurring-events-in-calendar-rails
But really dnt understand what they said. and also i have reviewed few suggested links but those are written in php. so i am unable to follow those links too. pls provide me some code to achieve this task. someone said we cannot achieve recurring event in fullcalendar. but i dont knw exactly whether it is right or wrong. if it is wrong then provide me some code to do this. or guide me if you have idea. thanks in advance.
This is my controller:
class EventsController < ApplicationController
before_action :set_event, only: [:show, :edit, :update, :destroy]
# GET /events
# GET /events.json
def index
#events = Event.all
end
# GET /events/1
# GET /events/1.json
def show
end
# GET /events/new
def new
#event = Event.new
end
# GET /events/1/edit
def edit
end
# POST /events
# POST /events.json
def create
#event = Event.new(event_params)
respond_to do |format|
if #event.save
format.html { redirect_to #event, notice: 'Event was successfully created.' }
format.json { render :show, status: :created, location: #event }
else
format.html { render :new }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /events/1
# PATCH/PUT /events/1.json
def update
respond_to do |format|
if #event.update(event_params)
format.html { redirect_to #event, notice: 'Event was successfully updated.' }
format.json { render :show, status: :ok, location: #event }
else
format.html { render :edit }
format.json { render json: #event.errors, status: :unprocessable_entity }
end
end
end
# DELETE /events/1
# DELETE /events/1.json
def destroy
#event.destroy
respond_to do |format|
format.html { redirect_to events_url, notice: 'Event was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_event
#event = Event.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def event_params
params.require(:event).permit(:title, :description, :start_time, :end_time)
end
end
This is my view:
<p id="notice"><%= notice %></p>
<h1>Listing Events</h1>
<table>
<thead>
<tr>
<th>Title</th>
<th>Description</th>
<th>Start time</th>
<th>End time</th>
<th colspan="3"></th>
</tr>
</thead>
<tbody>
<% #events.each do |event| %>
<tr>
<td><%= event.title %></td>
<td><%= event.description %></td>
<td><%= event.start_time %></td>
<td><%= event.end_time %></td>
<td><%= link_to 'Show', event %></td>
<td><%= link_to 'Edit', edit_event_path(event) %></td>
<td><%= link_to 'Destroy', event, method: :delete, data: { confirm: 'Are you sure?' } %></td>
</tr>
<% end %>
</tbody>
</table>
<br>
<%= link_to 'New Event', new_event_path %>
<div id="calendar"></div>
<script>
$('#calendar').fullCalendar({
events: '/events.json'});
</script>

Rails 4 has one relationship nested attribute throw undefined method exception

I use rails 4 and define one-one relationship between model book and isbn, but can not access the nested attribute. Below is the code
book.rb
class Book < ActiveRecord::Base
has_one :isbn
accepts_nested_attributes_for :isbn
end
isbn.rb
class Isbn < ActiveRecord::Base
belongs_to :book
end
books_controller.rb
class BooksController < ApplicationController
before_action :set_book, only: [:show, :edit, :update, :destroy]
# GET /books
# GET /books.json
def index
#books = Book.find_by_sql(["select * from books where price > ?", 20])
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 action: 'show', status: :created, location: #book }
else
format.html { render action: 'new' }
format.json { render json: #book.errors, status: :unprocessable_entity }
end
end
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 { head :no_content }
else
format.html { render action: '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 }
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, :price, isbn_attributes: [:number])
end
end
books\index.html.erb
<table>
<tr>
<th>#</th>
<th>name</th>
<th>author</th>
<th>price</th>
<th>ISBN</th>
<th colspan="3">operation</th>
</tr>
<% #books.each do |book| %>
<tr>
<td><%= book.id %></td>
<td><%= book.name %></td>
<td><%= book.author %></td>
<td><%= book.price %></td>
<td><%= book.isbn.number %></td>
<td><%= link_to 'detail', book %></td>
<td><%= link_to 'edit', edit_book_path(book) %></td>
<td><%= link_to 'del', book, confirm: 'Are you sure?', method: :delete %></td>
</tr>
<% end %>
</table>
but the "<%= book.isbn.number %>" throw exception: undefined method `number' for nil:NilClass.
How to fix this issue? Thanks!
The simplest way is to check for isbn.nil? before accessing its attributes.
But there are better ways of doing this.
Using delegate so that don't violate the Law of Demeter.
class Book < ActiveRecord::Base
has_one :isbn
accepts_nested_attributes_for :isbn
delegate :number, to: :isbn, allow_nil: true, prefix: true
end
# then in your view
book.isbn_number
Using decorators, draper being the most popular gem.
class BookDecorator < Draper::Decorator
delegate_all
def isbn_number
# view can be more complex
isbn.number unless isbn.nil?
end
end
# don't forget to wrap your book instance in controller
Decorators are used to accumulate view logic. Use them when you need something more complex than a simple check for existence. Also don't make make your models too fat with a lot of delegators/methods, use decorators instead.
In rare cases you may need your associations always built/created when parent was. You can do it in your controller. Also you can use ActiveRecord callbacks and build associations on parent initialisation which is not recommended because there are some side effects, in tests primarily.
This happened because for that particular book no isbn exists, to handle this add a condition to <%= book.isbn.number %>
<td><%= book.isbn.number unless book.isbn.blank? %></td>

Resources