Using a named scope - ruby-on-rails

I"m trying to use a named scope to set my users carrier but keep getting this error
undefined method `target' for #<ActiveRecord::Relation:0x5ee3e40>
app/models/user.rb:19:in `set_carrier'
app/controllers/users_controller.rb:49:in `block in create'
app/controllers/users_controller.rb:48:in `create'
<div class= "field">
<%= f.label :carrier %><br>
<%= f.collection_select(:carrier_name, Carrier.find(:all) ,:name, :name) %>
</div>
user.rb
class User < ActiveRecord::Base
acts_as_authentic
after_create :set_sub
after_create :set_universal
after_create :set_carrier
def set_sub
#self.roles << "subscriber"
self.roles_mask = 4
end
def set_universal
self.channels << Channel.find(1)
end
def set_carrier
#carrier = Carrier.with_name(self.carrier_name)
self.carrier<< #carrier
end
ROLES = %w[admin moderator subscriber]
#Each user can subscribe to many channels
has_and_belongs_to_many :channels
#Each user who is a moderator can moderate many channels
#has_many :channel_mods
has_and_belongs_to_many :modifies , :class_name => "Channel"
#Each user can receive many messages
has_and_belongs_to_many :messages
#Each user belongs to a carrier
belongs_to :carrier
#Filter users by role(s)
named_scope :with_role, lambda { |role| {:conditions => "roles_mask & #{2**ROLES.index(role.to_s)} > 0 "} }
def roles
ROLES.reject { |r| ((roles_mask || 0) & 2**ROLES.index(r)).zero? }
end
def roles=(roles)
self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum
end
def role_symbols
roles.map do |role|
role.underscore.to_sym # NOT role.name.underscore.to_sym (role is a string)
end
end
end
carrier.rb
class Carrier < ActiveRecord::Base
has_many :users
named_scope :with_name, lambda {|name| {:conditions => {:name => name}}}
end
user controller
class UsersController < ApplicationController
filter_resource_access
# GET /users
# GET /users.xml
def index
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #users }
end
end
# GET /users/1
# GET /users/1.xml
def show
##user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #user }
end
end
# GET /users/new
# GET /users/new.xml
def new
##user = User.new
#carriers = Carrier.find(:all)
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #user }
end
end
# GET /users/1/edit
def edit
##user = User.find(params[:id])
end
def create
##user = User.new(params[:user])
##user.channels << Channel.find(1)
respond_to do |format|
if #user.save
format.html { redirect_to(:channels, :notice => 'Registration successfully.') }
format.xml { render :xml => #user, :status => :created, :location => #user }
else
format.html { render :action => "new" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
def profile
#user = User.find(params[:id])
end
# PUT /users/1
# PUT /users/1.xml
def update
##user = current_user
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to(#user, :notice => 'User was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.xml
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to(users_url) }
format.xml { head :ok }
end
end
def delete
#user = User.find(params[:user_id])
#user.destroy
redirect_to :users
end
end

You might be using an array instead of a singular item. belongs_to relationships are either nil or a model.
You may have intended to do a direct assignment:
def set_carrier
self.carrier = Carrier.with_name(self.carrier_name).first
end
The << operator is used to append items to arrays, but carrier is not an array. This may trip up something deeper in Rails.

Just in case this helps anyone: I was getting this error message too with a model like this:
def Foo
has_many :bars
has_many :thingies, through: :bars
end
I was then doing this in the controller;
Foo.all.includes(:bars, :thingies)
and it blew up trying to go through scopes. The fix was to remove "bars" from the includes call - they will be automatically eager-loaded because "thingies" is being eager loaded.

Related

Edit model in has_many through relation

I want to edit a has_many through relation, but instead of editing the relation, it creates a new model.
In my form:
<%= form_for #service do |f| %>
<%= f.fields_for :service_users do |ac| %>
<% end %>
<% end %>
In my model:
class Service < ActiveRecord::Base
has_many :service_users
has_many :users, :through => :service_users
accepts_nested_attributes_for :service_users
end
Begin situation:
When i update the comments field:
After updating i see the edited relation as a duplication of the first one.
In some way i have to check if there're already relations present, but how?
Update:
My controller:
class ServicesController < ApplicationController
before_action :set_service, only: [:show, :edit, :update, :destroy, :users]
before_filter :authenticate_user!
# GET /services
# GET /services.json
def index
services = current_user.available_services
#available_services = services.group_by { |t| t.date.beginning_of_month }
end
# GET /services/1
# GET /services/1.json
def show
# service_users = current_user.service_users
#
# Service.find_each do |service|
# unless service_users.detect { |m| m.service_id == service.id }
# current_user.service_users.build service_id: service.id
# end
# end
#
#available_users = #service.available_users.group_by { |u| u.group }
#planned_users = #service.planned_users.group_by { |u| u.group }
#reserve_users = #service.reserve_users.group_by { |u| u.group }
end
# GET /services/new
def new
#service = Service.new
end
# GET /services/1/edit
def edit
#service.service_users.create
end
# POST /services
# POST /services.json
def create
#service = Service.new(service_params)
p service_params
respond_to do |format|
if #service.save
format.html { redirect_to #service, notice: 'Service was successfully created.' }
format.json { render action: 'show', status: :created, location: #service }
else
format.html { render action: 'new' }
format.json { render json: #service.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /services/1
# PATCH/PUT /services/1.json
def update
respond_to do |format|
p service_params[:service_users_attributes]
if #service.update(service_params)
format.html { redirect_to #service, notice: 'Service was successfully updated.' }
format.json { render action: 'show', status: :ok, location: #service }
else
format.html { render action: 'edit' }
format.json { render json: #service.errors, status: :unprocessable_entity }
end
end
end
def users
#users = #service.users
end
# DELETE /services/1
# DELETE /services/1.json
def destroy
#service.destroy
respond_to do |format|
format.html { redirect_to services_url }
format.json { head :no_content }
end
end
def destroy_association
if params[:id].present?
ServiceUser.find(params[:id]).delete
redirect_to root_path
end
end
def make_user_available_for_service
p '########'
p params
p #service
redirect_to root_path
end
private
# Use callbacks to share common setup or constraints between actions.
def set_service
#service = Service.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def service_params
params.require(:service).permit(:date, :comments,
service_users_attributes: [:user_id,
:service_id,
:availability,
:comments],
service_groups_attributes: [:service_id,
:group_id,
:start_time,
:end_time])
end
end
Try build instead of create.
Like this:
def edit
#service.service_users.build
end
And check your service_params.
Your missing an id for the service_users.

Rails Stripe - You must supply a valid card

in my app I am using the 'Stripe' gem to setup payments. Everything was going fine but whenever I submit the payment it gives me the error 'You must supply a valid card'.
Below is my code.
Ad Controller
class AdsController < ApplicationController
before_action :set_ad, only: [:show, :edit, :update, :destroy]
# GET /ads
# GET /ads.json
def index
#ads = Ad.order('created_at DESC').search(params[:search])
#ads_small = Ad.where(:size => "small").order('created_at DESC')
#ads_medium = Ad.where(:size => "medium").order('created_at DESC')
#ads_featured = Ad.where(:size => "featured").order('created_at DESC')
end
def myads
#ads_mine = Ad.where(:user_id => current_user.id )
end
# GET /ads/1
# GET /ads/1.json
def show
end
# GET /ads/new
def new
#ad = Ad.new
end
# GET /ads/1/edit
def edit
end
# POST /ads
# POST /ads.json
def create
#ad = Ad.new(ad_params)
#ad.user_id = current_user.id
respond_to do |format|
if #ad.save_with_payment
format.html { redirect_to #ad, notice: 'Ad was successfully created.' }
format.json { render action: 'show', status: :created, location: #ad }
else
format.html { render action: 'new' }
format.json { render json: #ad.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /ads/1
# PATCH/PUT /ads/1.json
def update
respond_to do |format|
if #ad.update(ad_params)
format.html { redirect_to #ad, notice: 'Ad was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: 'edit' }
format.json { render json: #ad.errors, status: :unprocessable_entity }
end
end
end
# DELETE /ads/1
# DELETE /ads/1.json
def destroy
#ad.destroy
respond_to do |format|
format.html { redirect_to ads_url }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_ad
#ad = Ad.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def ad_params
params.require(:ad).permit(:title, :url, :preview, :location, :size, :info, :search)
end
end
Ad Model
class Ad < ActiveRecord::Base
belongs_to :user
has_attached_file :preview, :styles => { :medium => "125x125^", :featured => "250x250^", :showpg => "400x400^" }, :convert_options => {:medium => "-gravity center -extent 125x125", :featured => "-gravity center -extent 250x250", :showpg => "-gravity center -extent 400x400"}
validates :title, length: { maximum: 35 }
validates :url, length: { maximum: 40 }
attr_accessor :stripe_card_token
def self.search(search)
if search
find(:all, :conditions => ['LOWER(title) ILIKE ? or LOWER(info) ILIKE ? or LOWER(location) ILIKE ?', ("%#{search.downcase}%"), ("%#{search.downcase}%"), ("%#{search.downcase}%")])
else
find(:all)
end
end
def save_with_payment
if valid?
customer = Stripe::Customer.create(description: "ad stripe customer", plan: "ad_f", card: stripe_card_token)
self.stripe_customer_token = customer.id
save!
end
end
end
ads.js.coffee
# Place all the behaviors and hooks related to the matching controller here.
# All this logic will automatically be available in application.js.
# You can use CoffeeScript in this file: http://coffeescript.org/
jQuery ->
Stripe.setPublishableKey($('meta[name="stripe-key"]').attr('content'))
ad.setupForm()
ad =
setupForm: ->
$('#new_ad').submit ->
$('input[type=submit]').attr('disabled', true)
ad.processCard()
false
processCard: ->
card =
number: $('#card_number').val()
cvc: $('#card_code').val()
expMonth: $('#card_month').val()
expYear: $('#card_year').val()
Stripe.createToken(card, ad.handleStripeResponse)
handleStripeResponse: (status, response) ->
if status == 200
$('#ad_stripe_card_token').val(response.id)
$('#new_ad')[0].submit()
else
alert(response.error.message)
$('input[type=submit]').attr('disabled', false)
Any help would be greatly appreciated. :)
In your Ad model, you have:
attr_accessor :stripe_card_token
and then you use the token in save_with_payment:
customer = Stripe::Customer.create(..., card: stripe_card_token)
self.stripe_customer_token = customer.id
So far so good. But you use ad_params to filter params in your controller when you create your Ad:
def ad_params
params.require(:ad).permit(:title, :url, :preview, :location, :size, :info, :search)
end
and I don't see :stripe_card_token in the permitted list anywhere. Presumably the #ad_stripe_card_token in your HTML looks like this:
<input type="hidden" name="ad[stripe_card_token]">
so you should be able to add :stripe_card_token to the permitted list in ad_params and get things going.

uninitialized constant ProductsController::Offer error?

I have an issue, I cant figure out what the problem is with the product controller error,
I will not render the product index view page which is what i want to work.
my code is here as follows :
offers controller
class OffersController < ApplicationController
attr_accessible :product , :reserve_price
def your_offer
#your_offer = Offer.new
end
def new
#offer = Offer.new = :your_offer
end
end
and Products Controller
class ProductsController < ApplicationController
before_filter :authenticate, :except => [:index, :show]
# GET /products
# GET /products.xml
def index
#offer = Offer.new
#products = Product.search(params[:search_query])
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #products }
end
end
# GET /products/1
# GET /products/1.xml
def show
#product = Product.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #product }
end
end
# GET /products/new
# GET /products/new.xml
def new
#product = Product.new
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #product }
end
end
# GET /products/1/edit
def edit
#product = Product.find(params[:id])
end
# POST /products
# POST /products.xml
def create
#product = current_user.products.new(params[:product])
respond_to do |format|
if #product.save
format.html { redirect_to(#product, :notice => 'Product was successfully created.') }
format.xml { render :xml => #product, :status => :created, :location => #product }
else
format.html { render :action => "new" }
format.xml { render :xml => #product.errors, :status => :unprocessable_entity }
end
end
end
# PUT /products/1
# PUT /products/1.xml
def update
#product = Product.find(params[:id])
respond_to do |format|
if #product.update_attributes(params[:product])
format.html { redirect_to(#product, :notice => 'Product was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #product.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /products/1
# DELETE /products/1.xml
def destroy
#product = Product.find(params[:id])
#product.destroy
respond_to do |format|
format.html { redirect_to(products_url) }
format.xml { head :ok }
end
end
end
Offer Model
class Offer < ActiveRecord::Base
belongs_to :product
has_many :reserve_prices
attr_accessible :product, :offer , :reserve_price
validates_presence_of :offer
validate :ensure_meets_reserve_price
private
def ensure_meets_reserve_price
if amount < self.product.reserve_price
errors.add(:amount, "does not meet reserve price")
end
end
private
def reserve_price
product.reserve_price
end
def your_offer
#your_offer = Offer.new
end
def new
#offer = Offer.new = :your_offer
end
end
product index viex snippet
<%= form_for #offer do |f| %>
<%= f.text_field :your_offer %>
<%= f.submit "Make Offer" %>
<% end %>
Could any one see where my eror is ?
Its complaining about #offer = Offer.new
Did you run the migration and restarted the server after creating offers?
Did you declare it as a resource in config/routes.rb as
resources :products, :shallow => true do
resources :offers # or at least just this line
end
Edit:
Get rid of this line and try again
attr_accessible :product, :offer , :reserve_price
is :offer a column in the offers table?
You cannot have columns from another model in attr_accessible.

Nested attributes in ROR

I'm trying to create an application where users can freely create shops and associated shop item for a specific shop is displayed when a show action is called but I seem to be doing something wrong. Any help here will be appreciated. I have attached shots of my code below.
class ShopItem < ActiveRecord::Base
belongs_to :shop
def self.find_shop_items_for_sale
find(:all, :order => "title", :conditions => ["shop_id = ?", #shop.id])
end
end
class Shop < ActiveRecord::Base
has_many :shop_items
end
#Controllers
class ShopsController < ApplicationController
def new
#shop = Shop.new
end
def create
#shop = Shop.new(params[:shop])
#shop.user_id = current_user.id
respond_to do |format|
if #shop.save
flash[:notice] = "Successfully created shop."
format.html {redirect_to(all_shops_shops_url)}
format.xml {render :xml => #shop, :status => :created, :location => #shop }
else
format.html {render :action => 'new'}
format.xml { render :xml => #shop.errors, :status => :unprocessable_entity }
end
end
end
def show
#shop = Shop.find(params[:id])
#shop_items = ShopItem.find_shop_items_for_sale
#shop_cart = find_shop_cart
end
class ShopItemsController < ApplicationController
def user
#per_page ||= 5
#user = User.find(params[:id])
#shop_items = ShopItem.find(:all, :conditions=>["user_id = ?", #user.id], :order=>"id desc")
end
def show
#shop_item = ShopItem.find(params[:id])
#shop = #shop_item.shop
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #shop_item }
end
end
# GET /shop_items/new
# GET /shop_items/new.xml
def new
#shop_item = ShopItem.new
#shop = Shop.find(params[:id])
##shop_items = ShopItem.paginate(:all, :condition=>["shop_id] = ?", #shop.id], :order=> "id desc", :page => params[:page],:per_page => #per_page)
#shop_items = ShopItem.find(:all, :conditions=>["shop_id = ?", #shop.id], :order=> "id desc")
#shop_item.shop_id = params[:id]
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #shop_item }
end
end
# GET /shop_items/1/edit
def edit
#shop_item = ShopItem.find(params[:id])
end
# POST /shop_items
# POST /shop_items.xml
def create
#shop_item = ShopItem.new(params[:shop_item])
#shop_item.user_id = current_user.id
respond_to do |format|
if #shop_item.save
flash[:notice] = 'Shop item was successfully created.'
format.html { redirect_to(#shop_item) }
format.xml { render :xml => #shop_item, :status => :created, :location => #shop_item }
else
#shop = Shop.find(#shop_item.shop_id)
##shop_items = ShopItem.paginate(:all, :condition =>["shop_id = ?", #shop.id], :order=> "id desc" , :page => params[:page], :per_page => #per_page)
#shop_items = ShopItem.find(:all, :conditions =>["shop_id = ?", #shop.id], :order=> "id desc")
format.html { render :action => "new" }
format.xml { render :xml => #shop_item.errors, :status => :unprocessable_entity }
end
end
end
If you specify that shop :has_many :shop_items, then you don't have to specify actions like find_shop_items_for_sale. Just call:
#shop = Shop.find(params[:id])
#shop_items = #shop.shop_items
Also trying to retrive all shop items for user (action user) is a bad idea. Instead take a look on will_paginate gem.
On the other side, your question isn't question at all and it would be much easier if you will ask a specific question, or just try to explain what problems you have.

Unable to set carrier

I'm trying to set the carrier for my new users but when i submit i get this errorr
Carrier(#37295244) expected, got
String(#15496392)
<div class= "field">
<%= f.label :carrier %><br>
<%= f.collection_select(:carrier, Carrier.find(:all) ,:name, :name) %>
</div>
usermodel
class User < ActiveRecord::Base
acts_as_authentic
after_create :set_sub
after_create :set_universal
after_create :set_carrier
def set_sub
#self.roles << "subscriber"
self.roles_mask = 4
end
def set_universal
self.channels << Channel.find(1)
end
def set_carrier
self.carriers<< self.carrier_name
end
ROLES = %w[admin moderator subscriber]
#Each user can subscribe to many channels
has_and_belongs_to_many :channels
#Each user who is a moderator can moderate many channels
#has_many :channel_mods
has_and_belongs_to_many :modifies , :class_name => "Channel"
#Each user can receive many messages
has_and_belongs_to_many :messages
#Each user belongs to a carrier
belongs_to :carrier
#Filter users by role(s)
named_scope :with_role, lambda { |role| {:conditions => "roles_mask & #{2**ROLES.index(role.to_s)} > 0 "} }
def roles
ROLES.reject { |r| ((roles_mask || 0) & 2**ROLES.index(r)).zero? }
end
def roles=(roles)
self.roles_mask = (roles & ROLES).map { |r| 2**ROLES.index(r) }.sum
end
def role_symbols
roles.map do |role|
role.underscore.to_sym # NOT role.name.underscore.to_sym (role is a string)
end
end
end
carrier model
class Carrier < ActiveRecord::Base
has_many :users
end
users controller
class UsersController < ApplicationController
filter_resource_access
# GET /users
# GET /users.xml
def index
#users = User.all
respond_to do |format|
format.html # index.html.erb
format.xml { render :xml => #users }
end
end
# GET /users/1
# GET /users/1.xml
def show
##user = User.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.xml { render :xml => #user }
end
end
# GET /users/new
# GET /users/new.xml
def new
##user = User.new
#carriers = Carrier.find(:all)
respond_to do |format|
format.html # new.html.erb
format.xml { render :xml => #user }
end
end
# GET /users/1/edit
def edit
##user = User.find(params[:id])
end
def create
##user = User.new(params[:user])
##user.channels << Channel.find(1)
respond_to do |format|
if #user.save
format.html { redirect_to(:channels, :notice => 'Registration successfully.') }
format.xml { render :xml => #user, :status => :created, :location => #user }
else
format.html { render :action => "new" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
def profile
#user = User.find(params[:id])
end
# PUT /users/1
# PUT /users/1.xml
def update
##user = current_user
respond_to do |format|
if #user.update_attributes(params[:user])
format.html { redirect_to(#user, :notice => 'User was successfully updated.') }
format.xml { head :ok }
else
format.html { render :action => "edit" }
format.xml { render :xml => #user.errors, :status => :unprocessable_entity }
end
end
end
# DELETE /users/1
# DELETE /users/1.xml
def destroy
#user = User.find(params[:id])
#user.destroy
respond_to do |format|
format.html { redirect_to(users_url) }
format.xml { head :ok }
end
end
def delete
#user = User.find(params[:user_id])
#user.destroy
redirect_to :users
end
end
I have not tested your code but at first sight I can see were might be the source of the error:
def set_carrier
self.carriers<< self.carrier_name
end
You assign carrier_name, probably a string to self.carriers which should hold an array of Carrier object.

Resources