How to pass id from different table in rails? - ruby-on-rails

Using Devise Gem to store user.
Created One to Many association between User to Project.
Created One to Many Association Between User and Site and Then One to Many Association between Project and Site.
But the error is i am not able to Assign project_id to Site from User Creation form. i am able to Assign from console. here is my code-
sites_controller.rb
def create
#site = current_user.sites.build(site_params)
respond_to do |format|
if #site.save
format.html { redirect_to #site, notice: 'Transactions was successfully Uploaded.' }
format.json { render :show, status: :created, location: #site }
else
format.html { render :new }
format.json { render json: #site.errors, status: :unprocessable_entity }
end
end
end
def site_params
params.require(:site).permit(:name, :amount)
end
site.rb(model)
belongs_to :user
belongs_to :project
User.rb
has_many :projects
has_many :sites
project.rb
has_many :sites, dependent: :destroy
How can i pass project_id on site creation. Is there any other simple way to resolve such problem?

Based on the comments in the question:
# project_id needs to be available to the method,
# in order to be added to site.
#
# Either pass it through params or get it from database
# based on your business logic.
site_params = site_params.merge({project_id: project_id})
#site = current_user.sites.build(site_params)
Should help.

Try permitting the foreign key as well.
def site_params
params.require(:site).permit(:name, :amount, :project_id)
end

Related

How to clean code and eliminate the NoMethodError exception

When a user creates an accounts, the code should allow that user to register a user account through Devise and then create an account, plus a company.
The code should redirect to a wizard setup using the wicked gem.
Users have roles (rolify) and are authorized with Cancancan.
The tables are setup using has_many :through association. This seems to work.
The models are as follows:
user
has_many :accounts_users
has_many :accounts, through: :accounts_users, dependent: :destroy
has_one :company, through: :accounts, dependent: :destroy
users_account
belongs_to :account
belongs_to :user
account
resourcify
has_many :accounts_users
has_many :users, through: :accounts_users, dependent: :destroy
has_one :company
company
belongs_to :account
The create account controller is the following:
def new
#account = Account.new
end
def create
if !current_user.present?
build_resource(sign_in_params)
account = Account.find_or_create_by(org_name: params[:user] [:account])
else
#account = current_user.accounts.create!(account_params)
end
# create a default account and company
#account.save!
current_user.add_role 'owner'
current_account = current_user.accounts.first
# create a company associated with the newly created account
if current_account.companies.empty?
company = current_account.companies.create(company_name: params[:org_name])
else
company = current_account.companies.first
end
resource.update(current_company: company.id)
respond_to do |format|
if #account.save
# redirect to the relevant wizard
format.html { redirect_to after_account_path(:add_account), notice: 'Account was successfully created.' }
else
format.html { render action: 'new' }
format.json { render json: #account.errors, status: :unprocessable_entity }
end
end
end
EDITED VERSION
def create
#account = Account.create(account_params.except(:company))
#account.save!
respond_to do |format|
if #account.save
create_company
format.html { redirect_to #account, notice: 'Account was successfully created.' }
format.json { render :show, status: :created, location: #account }
else
format.html { render :new }
format.json { render json: #account.errors, status: :unprocessable_entity }
end
end
end
def create_company
current_user.add_role 'owner'
current_account = current_user.accounts.first
if current_account.company.nil?
current_account.build_company(company_name: params[:org_name])
#company.save!
else
company = current_account.company
end
resource.update(current_company: company.id)
end
included in Application helper:
def current_account
current_user.accounts.first
end
def current_company
current_user.accounts.first.companies.first
end
it redirects (unexpected) to displaying (show) the Company data right after creation, I receive a nil / no method error.
the index and how controller are:
before_action :set_company, only: [:show, :edit, :update, :destroy,
:new]
def index; end
def show
#company = Company.find_by(id: params[:id])
end
def set_company
#company = current_account.company
end
This seems to work. Editing the Company is a challenge but should get there.
Any advices to get to a better code is welcome
Have you thought about just making the front end handle the case where #name isn't set yet?
<=% #company&.name %>
or
<=% #company.name || "Unknown" %>

How to send a mailer on update of an object in a HABTM join table

I have a User object and an Orgs object that are associated through a HABTM join table. I want to send an email to the users when the Orgs object is updated AND the Org.approved value is set to true. I have an approved boolean on the Org.
I think I've gotten most of the way there but I need help with the step of actually sending the email.
Here's my code
class OrgMailer < ApplicationMailer
default from: 'myemail#example.co'
def org_approved(user, org)
#user = user
#orgs = User.orgs.all
#url = 'http://example.com/login'
mail(to: #user.email, subject: 'Your listing has been approved.')
end
end
User.rb
class User < ApplicationRecord
# Include default devise modules. Others available are:
# :confirmable, :lockable, :timeoutable and :omniauthable
has_and_belongs_to_many :orgs, join_table: :orgs_users
end
Org.rb
class Org < ApplicationRecord
has_and_belongs_to_many :users, join_table: :orgs_users
# after_update :send_approved_listing_email, only: [:update]
attachment :company_image
def send_approved_listing_email
OrgMailer.org_approved(i).deliver_now if org.approved === true
end
end
UPDATED: ADDED ORG_CONTROLLER
I've edited my code to look like the answer below but am now getting a new error: uninitialized constant Org::OrgsUser
It's caused when I hit the #org.users << #user line in the create action.
If I delete this line, I'm able to create an org but it's not associating properly.
org_controller.rb
class OrgsController < ApplicationController
before_action :set_org, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!
def index
#orgs = Org.all
#tags = ActsAsTaggableOn::Tag.all
end
def show
end
def new
#org = Org.new
end
def contest
end
def edit
end
def create
#user = current_user
#org = Org.new(org_params)
#org.users << #user
respond_to do |format|
if #org.save
format.html { redirect_to thankyou_path, notice: 'Your listing was successfully created. Our team will approve your listing after review.' }
format.json { render :show, status: :created, location: #org }
else
format.html { render :new }
format.json { render json: #org.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if #org.update(org_params)
format.html { redirect_to #org, notice: 'Listing was successfully updated.' }
format.json { render :show, status: :ok, location: #org }
else
format.html { render :edit }
format.json { render json: #org.errors, status: :unprocessable_entity }
end
end
end
def destroy
#org.destroy
respond_to do |format|
format.html { redirect_to orgs_url, notice: 'Listing was successfully destroyed.' }
format.json { head :no_content }
end
end
def tagged
if params[:tag].present?
#orgs = Org.tagged_with(params[:tag])
else
#orgs = Org.postall
end
end
private
def set_org
#org = Org.find(params[:id])
end
def org_params
params.require(:org).permit(:twitter, :linkedin, :facebook, :name, :offer, :offercode, :url, :descrption, :category, :approved, :company_image, :tag_list => [])
end
end
I'm using active admin for my admin panel and have a batch action to update any selected orgs and approve them. I think what I'm missing is that in the send_approved_listing_email method I need to iterate through the orgs and email each user when the org is approved.
Right now nothing happens on update so I'm sure I'm not doing this correctly. What am I missing? How should I write this?
I would create a model for the join table rather than using habtm. That way you can use a callback when the join object is saved:
class User < ApplicationRecord
has_many :orgs_users
has_many :orgs, through: :orgs_users
end
class Org < ApplicationRecord
has_many :orgs_users
has_many :users, through: :orgs_users
end
class OrgsUsers < ApplicationRecord
belongs_to :org
belongs_to :user
after_create :send_approved_listing_email
def send_approved_listing_email
OrgMailer.org_approved(user, org).deliver_now if org.approved === true
end
end

Creating a join table record through two different controllers in rails

I'm trying to get my head around the best way to add a record to a join table through alternative controllers in rails.
I have various models in my app that will require this, but I'm focusing on these two first before I transcribe the method into others, so shall use this as the example. I have a Venue and Interest model which are to be connected through VenuesInterests model (it has a couple of extra optional attributes so isn't a HABTM relationship). A user can admin a Venue instance and/or an Interest instance and therefore there should be an ability to select Venues to attach to an Interest and likewise Interests to attach to a Venue. This should be done with an Add Venues link on the Interest instance view and an Add Interests link on the Venue instance view. This would then take the user to a list of the relevant instances for them to select ones they would like to select.
Here are my models:
Venue.rb
class Venue < ActiveRecord::Base
has_many :interests, through: :venue_interests
has_many :venues_interests, dependent: :destroy
accepts_nested_attributes_for :venues_interests, :allow_destroy => true
end
Interest.rb
class Interest < ActiveRecord::Base
has_many :venues, through: :venue_interests
has_many :venues_interests, dependent: :destroy
end
VenuesInterests.rb
class VenuesInterest < ActiveRecord::Base
belongs_to :interest
belongs_to :venue
validates :interest_id, presence: true
validates :venue_id, presence: true
end
This all seems fine, however it's the controller and views that I'm struggling with. I've tried adding an extra method add_interest to the Venues controller to do the job of the create method in the VenuesInterests controller, so that there will be a different view when adding Venues to an Interest than there would be adding Interests to a Venue, otherwise I don't know how I would do this. My current Venues controller is as follows:
VenuesController.rb:
class VenuesController < ApplicationController
before_filter :authenticate_knocker!, only: [:new, :edit, :create, :update, :destroy]
respond_to :html, :json
def index
#venues = Venue.all.paginate(page: params[:page]).order('created_at DESC')
end
def show
#venue = Venue.find(params[:id])
#hash = Gmaps4rails.build_markers(#venue) do |venue, marker|
marker.lat venue.latitude
marker.lng venue.longitude
marker.infowindow venue.name
end
end
def new
#venue = Venue.new
end
def edit
#venue = Venue.find(params[:id])
end
def create
#venue = current_knocker.venues.create(venue_params)
respond_to do |format|
if #venue.save!
format.html { redirect_to #venue, notice: 'Venue was successfully created.' }
format.json { render json: #venue, status: :created, location: #venue }
else
format.html { render action: "new" }
format.json { render json: #venue.errors, status: :unprocessable_entity }
end
end
end
def update
#venue = Venue.find(params[:id])
#venue.update_attributes(venue_params)
respond_to do |format|
if #venue.update_attributes(venue_params)
format.html { redirect_to(#venue, :notice => 'Your Venue was successfully updated.') }
format.json { respond_with_bip(#venue) }
else
format.html { render :action => "edit" }
format.json { respond_with_bip(#venue) }
end
end
end
def destroy
end
def add_interests
#venues_interests = VenuesInterest.new
#interests = Interests.all.paginate(page: params[:page]).order(:name)
end
private
def venue_params
params.require(:venue).permit(:admin... etc)
end
end
This isn't currently working as I'm not sure how to reference other classes within a controller, but the important thing I'd like to know is is there a better way to do this or am I (kind of) on the right track? If anyone has a good method (perhaps a jQuery plugin) for allowing multiple selection of instances for the view, that would be great too!
In my opinion, I would take advantage of the existing update method to add the relationship between Interest and Venue. I can do like this:
def update
#venue = Venue.find(params[:id])
#venue.update_attributes(params[:venue_params])
if params[:interest_ids].present?
#venue.interests = Interest.where(id: params[:interest_ids])
#venue.save
end
#more code to handle the rendering
end

polymorphic association with separate forms

I have one model, User, and then 2 other models: Editor and Administrator associated with the user model via a polymorphic association, so I want to have 2 type of users, and they will have different fields, but I need them to share certain features (like sending messages between both).
I thus need to keep the user ids in one table, users, and the other data in other tables, but I want that when a user signs up they first create the account and then the profile according to the type of profile they did pick.
model/user.rb
class User < ActiveRecord::Base
belongs_to :profilable, :polymorphic => true
end
model/administrator.rb
class Administrator < ActiveRecord::Base
has_one :user, :as => :profilable
end
model/Editor.rb
class Editor < ActiveRecord::Base
attr_accessor :iduser
has_one :user, :as => :profilable
end
controllers/user.rb
def create
#user = User.new(params[:user])
respond_to do |format|
if #user.save
if params[:tipo] == "editor"
format.html {redirect_to new_editor_path(:iduser => #user.id)}
else
format.html { redirect_to new_administrator_path(#user) }
end
# 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
controllers/editor.rb
def new
#editor = Editor.new
#editor.iduser = params[:iduser]
respond_to do |format|
format.html # new.html.erb
format.json { render json: #editor }
end
end
def create
id = params[:iduser]
#user = User.find(id)
#editor = Editor.new(params[:editor])
#editor.user = #user
respond_to do |format|
if #editor.save
format.html { redirect_to #editor, notice: 'Editor was successfully created.' }
format.json { render json: #editor, status: :created, location: #editor }
else
format.html { render action: "new" }
format.json { render json: #editor.errors, status: :unprocessable_entity }
end
end
end
views/editor/_form.html.erb
<div class="field">
<%= f.label :bio %><br />
<%= f.text_area :bio %>
<%= f.hidden_field :iduser%>
</div>
routes.rb
Orbit::Application.routes.draw do
resources :administrators
resources :editors
resources :users
When someone creates a new user they have to pic "Editor" or "Administrator" with a radio button, then using that parameter, the code will create an Editor or Administrator profile.
I am not sure if i have the association right, because it should be "User has a profile (editor/administrator)" but in this case is "Profile (administrator/editor) has a user".
The question:
Is the association right for what I want to accomplish?
How could I pass the user to the new editor method?
The way i have it right now is not working, and as I said, the association doesn't seem to be right.
Thanks for the time
Try and swap the association,
The user will have an administrator profile, and administrator profile will belong_to the user.
Administrator(:user_id, :other_attributes)
Editor(:user_id, :other_attributes)
So that,
class Administrator < ActiveRecord::Base
belongs_to :user
end
class Editor < ActiveRecord::Base
belongs_to :user
end
class User < ActiveRecord::Base
has_one :administrator
has_one :editor
end

Add current_user Devise to Mongoid relations

Hi Guys I have a Relationships in Mongoid and I can not add current_user to this relation for get the user that create the deal. A relation with 3 model.
I have three models user.rb, house.rb and deal.rb
user.rb Relationships (devise model)
# Relationships
has_many :houses, dependent: :destroy
has_many :deals, dependent: :destroy
key :title
house.rb
# Relationships
belongs_to :user
embeds_many :deals
deal.rb
# Relationships
embedded_in :house, :inverse_of => :deals
belongs_to :user
In my routes.rb
resources :houses do
resources :deals
end
In my houses_controller.rb in my create method I get current_user for each house of this side:
def create
##house = House.new(params[:house])
#house = current_user.houses.new(params[:house])
respond_to do |format|
if #house.save
format.html { redirect_to #house, notice: 'House was successfully created.' }
format.json { render json: #house, status: :created, location: #house }
else
format.html { render action: "new" }
format.json { render json: #house.errors, status: :unprocessable_entity }
end
end
end
In my deals_controller.rb I have the created method this:
def create
#house = House.find_by_slug(params[:house_id])
#user = User.find(:user_id)
#deal = #house.deals.create!(params[:deal])
redirect_to #house, :notice => "Comment created!"
end
How I can add to this last method create, the current_user that created the deal?
You can simply add these two lines to the create action:
#deal.user=current_user
#deal.save
And I would also suggest you not to use create! instead you should use .new and .save like in the scaffolded create actions! ;)

Resources