I see the above issue while accessing active admin show page for model "campaign". This might be due to friendly_id gem, but I'm unable to identify what exactly the issue is.
My campaign.rb file looks like following:
class Campaign < ApplicationRecord
extend FriendlyId
friendly_id :title, use: [:slugged, :history]
belongs_to :appeal
belongs_to :user
has_many :donations, dependent: :destroy
has_many :slugs, class_name: "FriendlyId::Slug", as: :sluggable, dependent: :destroy
validates :title, presence: true
validates :description, presence: true
validates :appeal_id, uniqueness: { scope: :user_id }
def normalize_friendly_id(value)
value.to_s.parameterize(preserve_case: true)
end
def self.first_by_friendly_id(id)
super(id.split("-").map(&:capitalize).join("-"))
end
private
def should_generate_new_friendly_id?
slug.blank? || title_changed?
end
end
and "campaigns.rb" contains:
ActiveAdmin.register Campaign do
# See permitted parameters documentation:
# https://github.com/activeadmin/activeadmin/blob/master/docs/2-resource-customization.md#setting-up-strong-parameters
#
# Uncomment all parameters which should be permitted for assignment
#
permit_params :title, :description, :appeal_id, :user_id, :slug
#
# or
#
# permit_params do
# permitted = [:title, :description, :appeal_id, :user_id, :slug]
# permitted << :other if params[:action] == 'create' && current_user.admin?
# permitted
# end
end
Related
I have a model Evaluation with a has_many with model Tag through evaluation_tags
I need to add this relationship in this Module, but i don't know how can i do this
class Evaluation < ApplicationRecord
belongs_to :user
belongs_to :teacher
belongs_to :school
belongs_to :subject
has_many :evaluation_tags
has_many :tags, through: :evaluation_tags
accepts_nested_attributes_for :evaluation_tags
validates :teacher_id, presence: true
validates :subject_id, presence: true
validates :school_id, presence: true
validates :user_id, presence: true
validates :rating, presence: true
end
module Wizard
module Evaluation
STEPS = %w(step1 step2 step3).freeze
class Base
include ActiveModel::Model
attr_accessor :evaluation
delegate *::Evaluation.attribute_names.map { |attr| [attr, "#{attr}="] }.flatten, to: :evaluation
def initialize(evaluation_attributes)
#evaluation = ::Evaluation.new(evaluation_attributes)
end
end
class Step1 < Base
validates :teacher_id, presence: true
end
class Step2 < Step1
validates :subject_id, presence: true
end
class Step3 < Step2
validates :school, presence: true
validates :user, presence: true
validates :rating, presence: true
end
end
end
When i access the step3 page, this error appears
undefined method `tag_ids' for #
Can anyone help me?
I think you can use ActiveSupport::Concern, like this:
module Wizard
module Evaluation
extend ActiveSupport::Concern
included do
has_many :tags, through: :evaluation_tags
end
end
end
then your class need to include it:
class Evaluation
include Wizard::Evaluation
end
What is the best approach to combine information from two different tables on Ruby on Rails, when building a JSON for Web Services purpose?
I want to combine my list of clients with a tag that is taken from another table than users table.
Here is how I proceed from the controller
def clients
#orders = #bar.orders
#users = User.where(id: #orders.pluck(:user_id).uniq).all
#tags = UserTag.where(bar: #bar, user_id: #orders.pluck(:user_id).uniq).all
end
The view is built this way
json.user_tags do
json.array!(#tags) do |user_tag|
json.extract! user_tag, :id, :bar_id, :user_id, :tag
end
end
json.users do
json.array!(#users) do |user|
json.extract! user, :id, :first_name, :last_name, :email, :facebook_id, :context, :created_at, :updated_at, :company, :phone, :birthdate, :stripe_customer_id, :bar_id, :role
end
end
The JSON generated with this code looks like this
I would like to integrate the tag field directly in users array, next to other users information such as on this illustration
The UserTag model is built like that
class UserTag < ActiveRecord::Base
belongs_to :user, :counter_cache => true
belongs_to :bar
validates_uniqueness_of :bar_id, :user_id, :scope => :bar_id
acts_as_paranoid without_default_scope: true
def self.default_scope
with_deleted
end
def api_error_message
errors.full_messages.join("\n")
end
end
And User model:
class User < ActiveRecord::Base
has_many :access_tokens, dependent: :destroy
belongs_to :club
belongs_to :bar
enum role: [:user, :club_owner, :waiter, :admin]
has_many :club_comments
has_many :club_subscriptions
has_many :artist_subscriptions
has_many :artist_votes
has_many :payments
has_many :carts
has_many :user_entrances
has_many :bookings, through: :user_entrances
has_many :booking_events, through: :user_entrances
has_many :cart_item_consumptions
has_many :clientlist_elements
has_secure_password
has_one :address, as: :addressable
accepts_nested_attributes_for :address
validates :password, length: {minimum: 8}, if: :validate_password?
validates :password_confirmation, presence: true, if: :validate_password?
validates :email, presence: true, if: :user_context_email
validates :email, email: true, if: :user_context_email
validates :email, :facebook_id, uniqueness: true, :allow_blank => true, :allow_nil => true
validates :first_name, presence: true
validates :last_name, presence: true
reverse_geocoded_by :latitude, :longitude
after_create :create_access_token
after_save :update_vote_position_if_needed
def validate_password?
password.present? || password_confirmation.present?
end
def name
"#{first_name.capitalize} #{last_name.capitalize}"
end
def create_access_token
AccessToken.create(user: self)
end
def user_context_email
context == 0
end
def user_context_fb
context == 1
end
def update_vote_position_if_needed
if self.latitude_changed? || self.longitude_changed?
self.delay.update_vote_position
end
end
def update_vote_position
self.artist_votes.each do |vote|
vote.latitude = self.latitude
vote.longitude = self.longitude
vote.save
end
end
def stripe_description
"#{first_name} #{last_name} - #{email}"
end
def stripe_customer_metadata
{"User_id" => self.id, "Firstname" => self.first_name, "Lastname" => self.last_name, "Email" => self.email, "Phone" => self.phone}
end
def api_error_message
errors.full_messages.join("\n")
end
end
EDIT
I tried the #krishnar solution, here is how the JSON looks like now
The users are duplicated and only users with tag appear (we need to display all users even those without tags)
Modify user model to have association:
class User < ActiveRecord::Base
# define user to user_tags association
has_many :user_tags
end
Join users table with user_tags and select user_tags id as tag to use in json file:
def clients
#orders = #bar.orders
#users = User.where(id: #orders.pluck(:user_id).uniq).joins("left join user_tags on users.id=user_tags.user_id and user_tags.bar_id='#{#bar.id}'").select("users.*","user_tags.id as tag")
#tags = UserTag.where(bar: #bar, user_id: #orders.pluck(:user_id).uniq).all
end
Now you can access tag in #users array:
json.users do
json.array!(#users) do |user|
json.extract! user, :id, :first_name, :last_name, :email, :facebook_id, :context, :created_at, :updated_at, :company, :phone, :birthdate, :stripe_customer_id, :bar_id, :role, :tag
end
end
I have a nested recourse called "transactions" inside another recourse "budgets".
All I'm trying to accomplish is for my users to be able to edit individual "transactions". However when I go to /1/transactions/1/edit I get a LocalJumpError saying "no block given (yield)".
There might be a very simple solution to this but I haven't been able to find it yet.
routes.rb:
resources :budgets, :path => '/' do
resources :transactions
end
budget.rb:
class Budget < ActiveRecord::Base
belongs_to :user
has_many :transactions
validates :amount, presence: true
validates :title, presence: true
validates :user, presence: true
validates :amount, numericality: true
extend FriendlyId
friendly_id :title, use: :slugged
def should_generate_new_friendly_id?
new_record?
end
end
transaction.rb
class Transaction < ActiveRecord::Base
belongs_to :user
belongs_to :budget
validates :amount, presence: true
validates :user, presence: true
validates :budget, presence: true
validates :date, presence: true
validates :amount, numericality: true
validates :is_positive, :inclusion => {:in => [true, false]}
end
transactions_controller.rb
def edit
#budget = Budget.friendly.find(params[:budget_id])
#transaction = #budget.transaction
end
And in the view transactions/edit.html.erb:
<%= form_for(#transaction) do |f| %>
What am I missing?
Naming a model Transaction conflicts with ActiveRecord::Transactions. You'll need to rename your model.
http://api.rubyonrails.org/classes/ActiveRecord/Transactions/ClassMethods.html
I have troubles creating the records in an association with rails 4. It's basically an association between Entry and Author, with a join table in the middle called AuthorsEntry. The schema is the following:
class Entry < ActiveRecord::Base
validates :name, presence: true
validates :from, presence: true
validates :to, presence: true
belongs_to :event
has_many :authors, through: :authors_entry
has_many :authors_entry
class AuthorsEntry < ActiveRecord::Base
validates :author, presence: true
validates :entry, presence: true
belongs_to :author
belongs_to :entry
end
class Author < ActiveRecord::Base
belongs_to :event
has_many :entries, through: :authors_entry
has_many :authors_entry
validates :name, presence: true
validates :event, presence: true
end
In my program_entries_controller.rb I have the following methods:
def create
#program_entry = Entry.new(program_entry_params)
author_ids_params.each do |id|
#program_entry.authors << AuthorsEntry.build(author_id: id)
end
#program_entry.event = #event
if #program_entry.save
flash[:notice] = t(:program_entry_created_successfully)
redirect_to organizer_event_program_entry_path(#event, #program_entry)
else
render :new
end
end
def program_entry_params
params.require(:program_entry).permit(
:name, :abstract, :'from(1i)', :'from(2i)', :'from(3i)',
:'from(4i)', :'from(5i)', :'to(1i)', :'to(2i)', :'to(3i)', :'to(4i)',
:'to(5i)'
)
end
def author_ids_params
params.require(:program_entry).permit(:author_ids => [])
end
I already have the authors saved in my database, the create action should just add a new record for the Entry model and the association (authors_entry) table. But when I try saving the entry it always returns "is_invalid" over authors_entry.
The join table should be named AuthorEntries to follow rails convention.
I've four user models: Zone, Product, User, Group
I want to choose what Users can sell a Product in a Zone, this is what Group does, with a many to many relation to User and a foreign key to one Product and one Zone. So I have one group per pair Zone/Product. I will also need to set custom attributes on that many to many relation so I used has_many :through Sell (I was unable to find a better name to describe the relation between Group and User).
So I ended up having 5 models: Zone, Product, User, Group, Sell.
It works fine, but now I'd need to select the next user available in a Group.
I was thinking to exploit Sell.id to find the user assigned to the same group with an higher id, if not present choose the first one again (this allows me to create a ring chain).
It would be useful to have a Group.next_user method.
Unfortunatly I can't figure out how to do this, I'd need help to find the next user available in the group (or the 1st one if there are no more users).
Follows the code for models all the models:
################
# models/group.rb
################
class Group < ActiveRecord::Base
has_many :sells
has_many :users, :through => :sells
belongs_to :zone
belongs_to :product
attr_accessible :priority, :product_id, :user_ids, :zone_id
end
################
# models/zone.rb
################
class Zone < ActiveRecord::Base
belongs_to :location
has_many :cities
has_many :groups
attr_accessible :name, :location_id
validates :location, :presence => true
end
################
# models/user.rb
################
class User < ActiveRecord::Base
after_create :create_calendar
before_destroy :destroy_calendar
belongs_to :location
belongs_to :mall
has_one :event_calendar
has_many :sells
has_many :groups, :through => :sells
# Include default devise modules. Others available are:
# :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable, :registerable,
# :recoverable, :rememberable,
devise :database_authenticatable, :trackable,
:validatable, :authentication_keys => [:username]
# Setup accessible (or protected) attributes for your model
attr_accessible :username, :password, :password_confirmation, :remember_me, :name,
:surname, :role, :location_id
# attr_accessible :title, :body
ROLES = %w[Admin Agente Hostess HostessAdmin]
validates_uniqueness_of :username, :case_sensitive => false
validates :username, :presence => true
validates_presence_of :role, :name, :surname, :location_id
validates :location, :presence => true
validates :role, :inclusion => { :in => ROLES, :message => "%{value} non รจ un ruolo valido." }
def display_name
"#{self.name} #{self.surname}"
end
def has_role?(role)
# convert the role string to a sybmol
self.role.downcase.gsub(/\s+/, "_").to_sym == role
end
private
def create_calendar
if self.has_role? :agente
calendar = EventCalendar.new({:user_id => self.id})
calendar.save()
end
end
def destroy_calendar
if self.has_role? :agente
calendar = EventCalendar.find_by_user_id(self.id)
calendar.destroy()
end
end
def email_required?
false
end
def email_changed?
false
end
end
################
# models/product.rb
################
class Product < ActiveRecord::Base
after_create :create_groups
before_destroy :destroy_groups
attr_accessible :name
def create_groups
for zone in Zone.all
group = Group.new({:zone_id => zone.id, :product_id => self.id})
group.save()
end
end
def destroy_groups
for zone in Zone.all
group = Group.find_by_product_id(self.id)
group.destroy
end
end
end
################
# models/sell.rb
################
class Sell < ActiveRecord::Base
belongs_to :user
belongs_to :group
end
Can you give me some help to get this done? Thanks!
If I get this right then addd this to your User model
scope :next, lambda { |p| {:conditions => ["id > ?", p.id], :limit => 1, :order => "id"} }
and this to your group model
def self.next_user
return User.first if Group.users.blank?
next_user = User.next(Group.users.last).first
return next_user || Group.users.first
end
This should do the trick. I didn't write test for this so you should test it :)