Rails web shop with Devise login and current_user - ruby-on-rails

I am making a web shop application in Rails with Devise as a login gem. The structure is as follows:
A user table which has a basket_id column and in its model I have set has_one :basket
The basket table belongs_to :user
In my basket_controller.rb I want to use the create method to get the user
# POST /baskets
# POST /baskets.json
def create
#basket = Basket.new(basket_params)
#basket.user_id = current_user.id
respond_to do |format|
if #basket.save
format.html { redirect_to #basket, notice: 'Basket was successfully created.' }
format.json { render :show, status: :created, location: #basket }
else
format.html { render :new }
format.json { render json: #basket.errors, status: :unprocessable_entity }
end
end
The problem is that the current_user method that should be automatically generated by Devise is not found and therefore the user_id in the Baskets table is not set. Also I have no idea where would I set the basket_id in the Users table or this should be done automatically because of the relationship defined in the models?
Any help would be appreciated. Thanks!

For current_user to work you need to add before_filter :authenticate_user! to your controller. If that does not work maybe is a csrf problem that you can solve placing
= csrf_meta_tags
In your layout.

Related

how to call actionmailer in rails admin controller?

I want to send a email to user after create something via rails admin.
I know I can call it in model callback but it's not considered as a good pratices
the best way is to put the actionmailer action after model save in the controller but I don't know how to do it in rails_admin controller
class UsersController < ApplicationController
# POST /users
# POST /users.json
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
# Tell the UserMailer to send a welcome email after save
UserMailer.welcome_email(#user).deliver_later
format.html { redirect_to(#user, notice: 'User was successfully created.') }
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: 'new' }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
end
What you want to do is not easy on rails admin because you cannot modify the controllers nor do you have access to them without monkey patching them.
I actually made a fork of rails admin for this functionality checkout the commit with the changes:
https://github.com/aliada-mx/rails_admin/commit/6251554efd1d83cdb418f42683ee55a4e27c2474
Just touched two files
And example usage
class User
after_save :on_admin_updates
attr_accessor :edited_in_rails_admin
def on_admin_updates
return unless edited_in_rails_admin
self.edited_in_rails_admin = false
UserMailer.welcome_email(self.id)
end
end
A bit clunky i know, PR´s welcome.
Have you tried to include your Mailer in admin_controller?
include UserMailer
Then in your create action UserMailer.some_mailer_action.deliver_now

Rails - how to reference namespaced table attributes in views

I am trying to learn how to use namespaces in my Rails 5 app.
I have an organisation model and I have also made a series of nested models under the folder name "stance". One of those models is called overview.
The associations are:
Organisation.rb
has_one :overview, class_name: Stance::Overview
accepts_nested_attributes_for :overview, reject_if: :all_blank, allow_destroy: true
Stance::Overview
class Stance::Overview < ApplicationRecord
belongs_to :organisation, inverse_of: :overview
My controllers for stance resources are nested under a folder called stance.
My routes are:
namespace :stance do
resources :overviews
end
In my stance view partial, I am trying to render the attributes from the overview table.
I have tried:
<p><%= #overview.internal_explanation %></p>
<p><%= #stance_overview.internal_explanation %></p>
<p><%= #stance.overview.internal_explanation %></p>
<p><%= #stance::overview.internal_explanation %></p>
I want to display this partial in my organisation show. I am trying to do that with:
<%= render 'stance/overviews/internal', overview: #overview %>
But I can't figure out how to access the overview table. Do I need to add a reference to 'stance' in the associations?
I can see that in the console I need to write:
o = Stance::Overview.create(internal_explanation: "test")
o = Stance::Overview.first
but I can't see how to use that in the code itself.
I can see in the console that there is a record for this attribute.
The name of the table in the schema is "stance_overview".
My organisation controller has:
class OrganisationsController < ApplicationController
before_action :set_organisation, only: [:show, :edit, :update, :destroy]
def index
#organisations = Organisation.all
end
def show
end
def new
#organisation = Organisation.new
#organisation.build_overview
end
def edit
#organisation.build_overview unless #organisation.overview
end
def create
#organisation = Organisation.new(organisation_params)
respond_to do |format|
if #organisation.save
format.html { redirect_to #organisation, notice: 'Organisation was successfully created.' }
format.json { render :show, status: :created, location: #organisation }
else
format.html { render :new }
format.json { render json: #organisation.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #organisation.update(organisation_params)
format.html { redirect_to #organisation, notice: 'Organisation was successfully updated.' }
format.json { render :show, status: :ok, location: #organisation }
else
format.html { render :edit }
format.json { render json: #organisation.errors, status: :unprocessable_entity }
end
end
end
def destroy
#organisation.destroy
respond_to do |format|
format.html { redirect_to organisations_url, notice: 'Organisation was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_organisation
#organisation = Organisation.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def organisation_params
params.fetch(:organisation, {}).permit(:title, :comment,
overview_attributes: [:internal_explanation, :external_explanation ]
)
end
end
I have also tried defining the strong params for organisation as:
stance_overview_attributes: [:internal_explanation, :external_explanation ]
I keep getting an error that says:
undefined method `internal_explanation' for nil:NilClass
Can anyone refer me to materials to help me learn how to use namespaces in my app. I am trying to understand the fundamentals of this so that I can bank some knowledge. I am finding things through trial and error but not understanding what's actually required (although in this case, none of my attempts are working out).
To access Overview model(table) when you working not in Stance namespace you have to use Stance::Overview. If working for example in a controller that in Stance namespace you can use just Overview for access.
To get access from the relation you don't need any additional notation just #organisation.overview.
If I understand correctly in you case you have to declare your partial as
<%= render 'stance/overviews/internal', overview: #organisation.overview %>
and in the partial you have to use overview without #.

Rails Associations: belongs_to has_many confusion

I've read through the following tutorial and found the curious line:
notice that the create function is written in such a way that there has be a #post before creating a #comment.
You can see the supporting controller code:
Class CommentsController < ApplicationController
----
def create
#post = Post.find(current_post)
#comment = #post.comments.create(post_params) ## 'Essential stuff'
respond_to do |format|
if #comment.save
format.html { redirect_to action: :index, notice: 'Comment was successfully created.' }
format.json { render :show, status: :created, location: #comment }
else
format.html { render :new }
format.json { render json: #comment.errors, status: :unprocessable_entity }
end
end
end
----
end
Indeed, "current_post" implies that the post was created BEFORE the comment.
But what if I want both to be created simultaneously? For example, suppose my USER has_many EMAILS, and each EMAIL belongs_to a USER. Then, when creating a new user, I may want to have an expandable form that allows the user to add one, two, three, or twenty emails while creating his account.
How could this be done?
Nested Attributes is the rails way of doing what you want to achieve.
Checkout http://railscasts.com/episodes/196-nested-model-form-part-1
You need to consider using nested form, have a look into this gem, very easy to implement. It will allow the user to add multiple emails as required.

Can't associate post to Devise user

I'm having extreme difficulty associating post to a user registered in devise.
I generated a post scaffold and got everything set up correctly in Devise.
I added a migration to the post that included a user_id field
The user model has_many :posts
The Post model belongs_to :user
For some reason I cannot connect the user with the post. Am I missing something?
thanks all!
My controller for posts
def create
#user = User.find(params[:id])
#post = #user.posts.create(params[:post])
respond_to do |format|
if #post.save
format.html { redirect_to #post, notice: 'Post was successfully created.' }
format.json { render action: 'show', status: :created, location: #post }
else
format.html { render action: 'new' }
format.json { render json: #post.errors, status: :unprocessable_entity }
end
end
end
First of all you need a user to associate a post:
#user = User.find(params[:id]) # or just use current_user as you are using Devise
As long as you have has_many association you can do the following:
#post = #user.posts.build(params[:post]) # to return newly created object without saving it to the database
#post = #user.posts.create(params[:post]) # to create and save record to the database
That's it.

Rails: Pass Parameters to New Controller during 'redirect_to'

I'm using Ryan Bates' Rails Cast on Wicked Wizard Forms to create a multi-step form. I don't have a current_user method defined (not using an authentication gem) - so, I'm trying to pass the user.id parameter during the redirect_to - unfortunately, I can't seem to get it to work. Any help is appreciated!
My user controller create method
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
format.html { redirect_to controller: 'user_steps', id: 'user.id' }
#format.html { redirect_to #user, notice: 'User was successfully created.' }#
format.json { render json: #user, status: :created, location: #user }
else
format.html { render action: "new" }
format.json { render json: #user.errors, status: :unprocessable_entity }
end
end
end
The user_steps controller that to which I am redirecting:
class UserStepsController < ApplicationController
include Wicked::Wizard
steps :gender, :items, :brands, :final
def show
render_wizard
end
end
You should pass it through as a param, ideally, which the redirect_to method will do for you if you use a proper route path.
Example:
redirect_to(user_steps_path(#user))
In your case, if you don't have a named route, you might do this:
redirect_to(controller: 'user_steps', id: #user.to_param)
In URLs it's advisable to use the to_param method. id is used for database queries.
What you're passing in is literally 'user.id' as a parameter. It will not be evaluated.

Resources