build_association working? - ruby-on-rails

I have two models with a one-to-one association.
class User < ActiveRecord::Base
has_one :setting
end
class Setting < ActiveRecord::Base
belongs_to :user
end
Each model has plenty of fields and user is used quite extensively by a non rails external server, which is why I have separated the tables.
I am trying to use the build_association but all I get is undefined method `build_setting' for nil:NilClass. I want to do this because I want a single form with fields from both models to setup a new user.
In my user controllers new method I try this:
def new
#user = User.new
#setting = #user.setting.build_setting
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #user }
end
end
Which throws:
NoMethodError in UsersController#new
undefined method `build_setting' for nil:NilClass
Why? According to the api docs this is the way to do it.
Doing this seems to work, but its not the right way (or is it?):
def new
#user = User.new
#setting = Setting.new
#user.setting=#setting
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #user }
end
end

You need to use:
#setting = #user.build_setting
This is after an edit, so if you like this answer, accept Mahesh's below.

In your users model add
class User < ActiveRecord::Base
has_one :setting
validates_associated :setting
end
and then use
#setting = #user.build_setting

Related

Ruby on rails Association Records returns empty But in rails console it returns something

in the registration.rb
class Registration < ActiveRecord::Base
......
has_many :cash_transactions
after_destroy :destroy_cash_transaction
def first_cash_transaction
self.cash_transactions.first
end
def destroy_cash_transaction
if first_cash_transaction.registrations.count == 0
self.cash_transactions.find(first_cash_transaction).destroy
end
end
in cashtransaction.rb
class CashTransaction< ActiveRecord::Base
......
has_many :registrations
so, when I destory the registration, it will destroy_cash_transaction associated with the registration.
In the rails console, I tried:
Registration.find(some_id).cash_transactions
The console returns some records
However, when I tried to delete a registration, it will invoke destroy_cash_transaction, which will call first_cash_transaction, which returns empty records.
Can anyone help me with this? Thank you very much.
-----updated------
in participant controller
def destroy
if #registration.destroy
respond_to do |format|
format.html {redirect_to admin_events_participants_path, :notice => "#{#registration.email}'s registration has been deleted."}
end
else
respond_to do |format|
format.html {
flash[:warning] = print_out_message('form-destroy','registration')
redirect_to admin_events_participants_path
}
end
end
def load_registration
#registration = #event.registrations.find(params[:registration_id])
end

Rails: notifications using GetStream and Acts As Follower gems

I'm using getstream and acts as follower to build a notification and news feed for my project. When following a certain user, that user is supposed to get a notification of such following. I'm able to follow and unfollow users, but getstream gives the following error:
Something went wrong creating an activity: undefined local variable or method `user' for #<Follow:0x007ffaa70c9398>
Completed 500 Internal Server Error in 37ms
NameError (undefined local variable or method `user' for #<Follow:0x007ffaa70c9398>):
app/controllers/users_controller.rb:160:in `follow_user'
Rendered /usr/local/lib/ruby/gems/2.2.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_source.erb (3.1ms)
Rendered /usr/local/lib/ruby/gems/2.2.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_trace.text.erb (0.8ms)
Rendered /usr/local/lib/ruby/gems/2.2.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/_request_and_response.text.erb (0.9ms)
Rendered /usr/local/lib/ruby/gems/2.2.0/gems/actionpack-4.2.0/lib/action_dispatch/middleware/templates/rescues/diagnostics.text.erb (108.1ms)
This if what my follow.rb file looks like:
class Follow < ActiveRecord::Base
extend ActsAsFollower::FollowerLib
extend ActsAsFollower::FollowScopes
# NOTE: Follows belong to the "followable" interface, and also to followers
belongs_to :followable, :polymorphic => true
belongs_to :follower, :polymorphic => true
include StreamRails::Activity
as_activity
def activity_notify
[StreamRails.feed_manager.get_notification_feed(self.followable_id)]
end
def activity_object
self.followable
end
def block!
self.update_attribute(:blocked, true)
end
end
And in user.rb I have:
acts_as_followable
acts_as_follower
and nothing else referencing the Follow model. Any ideas what I'm doing wrong ?
EDIT:
Here is my follow and unfollow code in the users controller. Line 160 is if #follower.follow(#following), and likewise for unfollowing:
def follow_user
#follower = User.find_by_username(params[:username])
#following = User.where(id: params[:following_id]).first
#user = #following
if #follower == #following
respond_to do |format|
flash.now[:warning] = "Cannot follow yourself."
format.js { render file: "/app/views/layouts/notice.js.erb" }
end
end
if #follower.follow(#following)
StreamRails.feed_manager.follow_user(#follower.id, #following.id)
respond_to do |format|
format.js { render file: "/app/views/users/follow.js.erb" }
end
else
respond_to do |format|
flash.now[:info] = "Error."
format.js { render file: "/app/views/layouts/notice.js.erb" }
end
end
end
def unfollow_user
#follower = User.find_by_username(params[:username])
#following = User.find(params[:following_id])
#user = #following
if #follower.stop_following(#following)
StreamRails.feed_manager.unfollow_user(#follower.id, #following.id)
respond_to do |format|
format.js { render file: "/app/views/users/follow.js.erb" }
end
else
respond_to do |format|
flash.now[:info] = "Error."
format.js { render file: "/app/views/users/add_flag.js.erb" }
end
end
end
The stream-rails gem assumes that your model has a user attribute to lookup the actor of the activity. You can change this behavior by implementing the activity_actor method in your Follow model.
For example:
class Follow < ActiveRecord::Base
def activity_actor
self.follower
end
end
This will create activities such as "x followed y" when a follow model is created (as well as the logic that you already have implemented to create actual follow connections between feeds).

forbidden attribute error rails 4 Carrierwave

Have a issue with a controller file which i have narrowed down to a method
Controller
def create
#gallery = Gallery.new(params[:gallery])
if #gallery.save
flash[:notice] = "Successfully created gallery."
redirect_to #gallery
else
render :action => 'new'
end
end
private
def gallery_params
params.require(:gallery).permit(:name, :gallery, :gamepic)
end
end
the problem is that there is no attr_accessible in the controller or the model
model
class Gallery < ActiveRecord::Base
has_many :gamepics
private
def gallery_params
params.require(:gallery).permit(:name, :gallery, :gamepic)
end
end
Try passing the strong parameters method into Gallery.new instead of params[:gallery].
My understanding of this is that, the hash returned from that method is what should be used anyways. So you'd have:
#gallery = Gallery.new(gallery_params)
If you only need certain params from your :permit call, just make a new strong params method and use that one.

How to restrict foreign keys in Rails' update controller action?

In my Rails app I have invoices which in turn can have many projects.
model:
class Invoice < ActiveRecord::Base
attr_accessible :project_id
end
controller:
class InvoicesController < ApplicationController
before_filter :authorized_user, :only => [ :show, :edit, :destroy ]
before_filter :authorized_project, :only => [ :create, :update ]
def create # safe
#invoice = #project.invoices.build(params[:invoice])
if #invoice.save
flash[:success] = "Invoice saved."
redirect_to edit_invoice_path(#invoice)
else
render :new
end
end
def update # not safe yet
if #invoice.update_attributes(params[:invoice])
flash[:success] = "Invoice updated."
redirect_to edit_invoice_path(#invoice)
else
render :edit
end
end
private
def authorized_user
#invoice = Invoice.find(params[:id])
redirect_to root_path unless current_user?(#invoice.user)
end
def authorized_project
#project = Project.find(params[:invoice][:project_id])
redirect_to root_path unless current_user?(#project.user)
end
end
My biggest concern is that a malicious user might, one day, create an invoice that belongs to the project of another user.
Now thanks to the help of some people on this board I managed to come up with a before_filter that makes sure that this won't happen when a project is created.
The problem is I don't understand how to apply this filter to the update action as well.
Since the update action does not make use of Rails' build function, I simply don't know how to get my #project in there.
Can anybody help?
In your case I would start from current_user, not #project (provided User has_many :invoices):
current_user.invoices.build(params[:invoice])
Also instead of explicitly check current_user?(#invoice.user) you can do:
def find_invoice
#invoice = current_user.invoices.find(params[:id])
end
def find_project
#project = current_user.projects.find(params[:invoice][:project_id])
end
Wrong invoice or project will throw 500 which you may or may not want to handle.
If User has_many :invoices, :through => :projects and Project hence has_many :invoices then:
def find_invoice
#invoice = #project.invoices.find(params[:id])
end
The #project.invoices.build method creates a new Invoice that is automatically associated with that particular #project. You don't have to do any work, and there's no risk of it being linked to the wrong project.
You'll want to be sure that project_id is not an accessible attribute, though.

Nil class error

I want to display the related products to a certain need, just the picture and the name nothing more depending on the categorie
here is mu controller
class RelatedneedsController < ApplicationController
def index
#relatedneeds = RelatedNeed.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #relatedneeds }
end
end
def show
s1 = '#need.category.name'
s2 = '#relatedneed.category.name'
if s1.eql?(s2)
#relatedneed = relatedneed.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #need }
end
end
end
def get_name
#relatedneed.name
end
end
and this my model
class Relatedneed
include Mongoid::Document
include Mongoid::Paperclip
mapping do
indexes :name
end
field :name, type: String
belongs_to :category
belongs_to :user
end
and this is show.haml file
%h1
%b= #need.name
#container{:style => "width:1000px"}
#desc{:style => "height:400px;width:400px;float:left;"}
=image_tag #relatedneed.photo.url(:normal)
this is my index.haml file
%h1= #relatedneed.get_name
#container{:style => "width:1000px"}
#desc{:style => "background-color:#EEEEEE;height:400px;width:400px;float:left;"}
= link_to "Check Need", new_need_path
I don't know if their is something missing and i get this error
NoMethodError in RelatedneedsController#index
undefined method `key?' for nil:NilClass
Your index.haml has #relatedneed.get_name but you have not set #relatedneed in your controller, only #relatedneeds. Is it as simple as that?
Also, your show method in the controller makes no sense to me. You have put your instance variables inside strings! You need to set your instance variables with a database query via the model first. Your get_name method looks like it belongs in a model as well rather than a controller.

Resources