Rich many-to-many assosiation. Only allow one record - ruby-on-rails

I need to limit my rich many-to-many association table to only one association per unique par. (rails).
That means i want terminals (model 1) and subscriptions (model 2) to have one custom_price (rich join) not any more than that.
How is this done most elegantly?
So far i have done:
def new_custom_price
#terminal_id = params[:terminal_id]
#subscription_id = params[:subscription_id]
#custom_price = CustomPrice.find_or_initialize_by_terminal_id_and_subscription_id( #terminal_id, #subscription_id)
render action: 'custom_price'
end
def create_custom_price
#terminal_id = params[:terminal_id]
#subscription_id = params[:subscription_id]
#custom_price = CustomPrice.new(custom_price_params.merge( :terminal_id => #terminal_id, :subscription_id => #subscription_id))
respond_to do |format|
if #custom_price.save
format.js { render action: 'add_custom_price' }
else
format.js { }
end
end
end

Two things you can do to handle this: (This is assuming "price" is the unique part of the many to many relationships)
1) Validation in CustomPrice
validates :price, uniqueness: {scope: [:terminal_id, :subscription_id]}
Unique Price on CustomPrice with a scope of Terminal and Subscription IDs
http://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates
2) Use helpers
CustomPrice.find_or_create_by(custom_price_params.merge( :terminal_id => #terminal_id, :subscription_id => #subscription_id))
Similar to the one used in your new action
http://api.rubyonrails.org/classes/ActiveRecord/Relation.html#method-i-find_or_create_by

Related

How to find the ids used by current user

I have created a quiz and i displayed the items in one per page.. i want the values of question id that is visited by the current user . in this code i give next and it render the question i want the visited question id by current user
def next
#user = current_user
#student = Student.find_by_admission_no(#user.username)
#exam_group = ExamGroup.find_by_id(params[:exam_group_id])
#answer = Answer.new(params[:ans])
#answer.answer = params[:answer]
#answer.exam_group_id = #exam_group.id
#answer.user_id = #user.id
passed_question = params[:passed_question]
#answer.questions_id = passed_question
next_question = params[:next_question]
#question = Question.find_by_id(passed_question)
#module = Question.find_by_sql ["SELECT student_additional_field_id FROM questions WHERE id=#{passed_question}"]
student_additional_field_id = #module[0].student_additional_field_id
#questions = Question.find(:all, :conditions => [' exam_group_id=? && student_additional_field_id=? ',#exam_group,student_additional_field_id], :offset => #ans)
#ques = []
#questions.shuffle.each do |a|
#ques.push a.id unless a.id.nil?
end
a = #ques[0]
session[:ques_id] = a
#answer.modules_id = student_additional_field_id
if params[:answer] == #question.is_answer
#answer.marks = 1
else
#answer.marks = 0
end
if #answer.save
#ans = Question.find_by_id(a, :conditions => [' id not in (?) && exam_group_id=?',answered, #exam_group])
unless #ans.nil?
render(:update) do |page|
page.replace_html 'main', :partial => 'ans', :object => #ans
end
else
render(:update) do |page|
page.replace_html 'main', :partial => 'ans2'
end
end
end
end
It seems your problem is to do with Rails model associations:
Why do we need associations between models? Because they make common
operations simpler and easier in your code. For example, consider a
simple Rails application that includes a model for customers and a
model for orders. Each customer can have many orders
ActiveRecord Associations
ActiveRecord associations allow you to define a primary_key (typically an ID), which you can then reference on other tables through a foreign_key. The foreign key is typically a table column which will be called something like user_id, or another type of ID
You can associate your models using these functions:
belongs_to
has_one
has_many
has_many :through
has_one :through
has_and_belongs_to_many
To answer your question, you're obviously getting the current_user ID okay - so if you managed to get the relations set up correctly, you could literally call the data in this way:
#user = User.find(current_user.id)
#exam_group = #user.exams_groups
I would go through your code & put more info into it.... but I think you need to learn about ActiveRecord associations first

Get value from text field and store it as array

I have a text field in my database called departments where i want to store the list of departments. The user will enter the name of departments with comma separation. For example:
department1, deaprtment2, department3
I want this value to be stored as array when the user submits the form. Also, i want the list of departments to show as a drop-down. Finally, while updating the table , the department field should also be editable as before(update by entering texts separated by commas).
EDIT:
I have added this to my model:
class Org < ActiveRecord::Base
serialize :department, Array
attr_accessible :name, :department
before_validation :update_department
validates :name, presence: true
def update_department
if department_changed? and department.is_a?(String)
self.department = self.department.split(',').collect(&:strip)
end
end
end
and the view:
<%= f.text_area :department, :cols => "10", :rows => "10" %>
now Whenever i try to sign up, the department field already has [] present and when i try to update the department is already ["[department1", "department2]"].
I want [] to be removed while signing up and only department1, department2 to show up when updating.
Please Help.
The best way to do this would be via your models. I am assuming that you have a model called Org and another called Department and that you have defined a has many relationship between the two. All you then need to do is in your Org model add the following code:
def department_list
departments.collect { |d| d.department_name }.join(', ')
end
def department_list=(text)
if id && text
departments.destroy_all
text.split(',').each do |d|
departments.create(department_name: d.strip.capitalize)
end
end
end
Then in your view add a text box using #org.department_list.
EDIT:
Based on your expanded question, you have department field in an org model that you want to store and show as an array and but edit as a simple text field. My thoughts on this was that I don't like the idea of storing department data a field in org, it is a one to many relationship so department should be a separate model. I would remove the department field from org. Then create a migration to create a departments table. It should look something like this:
class CreateDeparments < ActiveRecord::Migration
def change
create_table :departments do |t|
t.integer :org_id
t.string :department_name
t.timestamps
end
end
end
Next in the Department model add this line of code:
belongs_to :org
In the org model add the following:
has_many :departments, dependent: :destroy
def department_list
departments.collect { |d| d.department_name }.join(', ')
end
def department_list=(text)
if id && text
departments.destroy_all
text.split(',').each do |d|
departments.create(department_name: d.strip.capitalize)
end
end
end
In your controllers and views you now have the following:
#org = Org.first
# List of departments as an array for a select
#org.departments
# A comma separated string for text boxes
#org.department_list
The department_list method can now be used to display the list in a text box and also be used to post and changes back. So you your view code just becomes this:
<%= f.text_area :department_list, :cols => "10", :rows => "10" %>
You will probably need to amend your org controller by changing the create to something like this:
def create
#org = Org.new(params[:org])
respond_to do |format|
if #org.save
#org.department_list = params[:org][:department_list]
format.html { redirect_to org_url,
notice: "#{#org.name} was successfully created" }
format.json { render json: #org,
status: :created, location: #org }
else
format.html { render action: "new" }
format.json { render json: #org.errors, status: :unprocessable_entity }
end
end
end
If you are still stuck I have a complete webiste on github that you can look through. For you it is orgs and departments and on mysite it is people and skills or people and credits. This is the link:
https://github.com/davesexton/CKCASTING

Looking for a way to return all nested associations using deep_clonable

I have a nested association where I have Rubric > Indicator > Question. In this gist you can see I step through the association correctly, then try to to clone the object and its associations. However, notice I have an empty array for klone.questions. I can do klone.indicators.first.questions and retrieve all questions associated with the first indicator, but I am looking for a way to retrieve all questions associated with a rubric (klone in this case).
https://gist.github.com/1389697
I'm assuming you're using has_many :questions, :through => :indicators. Is there a chance this is not compatible with the deep clone in the way you're using it? What do you get with klone.indicators.first.questions?
Its looks like deep_clonable cannot handle has_many :through type associations. I ended up doing this by hand like this:
def create
template = Template.find params[:template][:id]
params[:section_ids].each do |section|
#rubric = Rubric.new(template.attributes.merge(:name => template.name))
#rubric.section_id = section
#rubric.save
template.indicator_templates.each do |i|
indicator = Indicator.new(:name => i.name, :rubric_id => #rubric.id)
indicator.save
i.question_templates.each do |q|
question = Question.new(:name => q.name, :indicator_id => indicator.id)
question.save
end
end
end
if #rubric.save
redirect_to rubrics_path, :notice => "Successfully created rubric."
else
render :action => 'new'
end
end
So for the 3 models I am trying to clone (Rubrics, Indicators and Questions) I created 3 other models that basically mimic these models. I called them Template (for Rubric), IndicatorTemplate(for Indicators) and QuestionTemplate(for Questions). Then I create a new Rubric, and step through the indicators and questions making the proper associations along the way.

acts_as_taggable_on with permissions required to create new tags

How can I prevent users from adding new tags which don't already exist in the tags db?
I want them to be able to add any tags that already exist to another model which they can fully edit, but not be able to create new tags if they don't yet exist?
I'm using declarative_auth so some users with permissions should be create to add whatever tags they want.
user.rb
acts_as_tagger
post.rb
acts_as_taggable_on :features
https://github.com/mbleigh/acts-as-taggable-on
UPDATE:
This seems to do it except I can't get the error message variable to work:
validates :feature_list, :inclusion => {
:in => SomeModel.tag_counts_on(:features).map(&:name),
:message => "does not include {s}" }
I havn't used acts_as_taggable, but can you pass normal rails validations?
# LIKE is used for cross-database case-insensitivity
validates_inclusion_of :name => lambda { find(:all, :conditions => ["name LIKE ?", name]) }
Could probably be more robust and rails validation like but this works:
validate :valid_feature_tag
def valid_feature_tag
invalid_tags = false
feature_list.each do |tag|
list = SomeModel.tag_counts_on(:features).map(&:name)
unless list.include?(tag)
invalid_tags = true
end
end
unless invalid_tags == false
errors.add(:feature_list, 'cannot contain new tags, please suggest new tags to us')
return false
else
return true
end
end
Here's an efficient and clean way to enforce allowed tags:
validate :must_have_valid_tags
def must_have_valid_tags
valid_tags = ActsAsTaggableOn::Tag.select('LOWER(name) name').where(name: tag_list).map(&:name)
invalid_tags = tag_list - valid_tags
if invalid_tags.any?
errors.add(:tag_list, "contains unknown tags: [#{invalid_tags.join(', ')}]")
end
end

How to copy or clone model?

I have a model Book with attributes id, name, price. I have an instance of Book:
b1 = Book.new
b1.name = "Blah"
b1.price = 12.5
b1.save
I would like to copy b1, create another instance of the Product model. I'm tryid p1=b1.clone then p1.save but it didn't work. Any idea?
And my environment is:
Netbeans 6.9 RC2
JRuby 1.5.0
EDITED:
My TemporaryProduct model:
class Admin::TemporaryProduct < ActiveRecord::Base
def self.update_from_web_service(web_service_url)
response = HTTParty.get(web_service_url)
response["webServiceResult"]["product"].each do|element|
unless exists? :orignal_product_id => element['id']
create!(
:name => element['name'],
:price => element['price'],
:amount => element['amount'],
:description => element['description'],
:orignal_product_id => element['id'],
:image => element['image'],
:shop_account_number => element['shopAccountNumber'],
:unit => element['unit']
)
end
end
end
end
Product is create action:
def create
#temporary_products = Admin::TemporaryProduct.find_all_by_orignal_product_id(params[:product])
#product = Admin::Product.new(#temporary_products.attributes)
# #product = #temporary_products.clone
respond_to do |format|
format.html { redirect_to(admin_products_url, :notice => 'Admin::Product was successfully created.') }
end
end
I want to clone all b1's attributes to p1 model.
I think you want:
b2 = Book.create(b1.attributes)
Edit:
Given your create action above, I think what you want to do is change the line which starts #product to
#temporary_products.each {|tp| Admin::Product.create(tp.attributes)}
That will create a new Product object for each TemporaryProduct object, using the same attributes as the TemporaryProduct. If that's not what you want, let me know.
You can make duplicate record using dup in rails For Example,
b1 = Book.create(name: "example", price: 120)
b1.save
duplicate_record = b1.dup
duplicate_record.save!
or you can create first new record and then make a duplicate
Hope this is useful for you.
If by didn't work you mean that there is no new record in the database then you probably want to set the id of p1 to null before you save. If the clone has the same id as the original then it would appear to represent the same object.

Resources