Just started playing with Ruby (no IT background) and until now went it quite well. But since two days I'm stuck and don't understand what's going wrong... so many thanks already for helping me out with this problem!! The situation is as described below:
I created a currencymaster table with the following columns: currmasdesc:string, currmasiso:string.
I created a currencyrate table with the following columns: currratemasteridd:integer, currratemasteridc:integer, currraterate:decimal, currratedate:date. Whereby the column currratemasteridd reflects the Dominant Currency and the currratemasteridc reflects the Converted Currency to generate combined a currency-pair.
The models/currencymaster.rb looks like this:
class Currencymaster < ActiveRecord::Base
has_many :CurrencyRateDom, :class_name => "Currencyrate", :foreign_key => "CurrRateMasterIDD"
has_many :CurrencyRateConv, :class_name => "Currencrate", :foreign_key => "CurrRateMasterIDC"
end
The models/currencyrate.rb looks like this:
class Currencyrate < ActiveRecord::Base
belongs_to :CurrencyDominant, :class_name => 'Currencymaster' , :foreign_key => "CurrRateMasterIDD", :validate => true
belongs_to :CurrencyConverted, :class_name => 'Currencymaster' , :foreign_key => "CurrRateMasterIDC", :validate => true
end
The controllers/currencyrates_controller.rb looks like this:
class CurrencyratesController < ApplicationController
# GET /currencyrates
# GET /currencyrates.json
def index
#currencyrates = Currencyrate.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: #currencyrates }
end
end
# GET /currencyrates/1
# GET /currencyrates/1.json
def show
#currencyrate = Currencyrate.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: #currencyrate }
end
end
end
Now is my problem that I can't show, in the view/currencyrates/index.html.erb , the related currencymaster.currmasiso instead of the currratemasteridd & currratemasteridc stored in the table currencyrate.
I hope all information is avaibale in this question, else please let me know when other information is needed. Thanks again!
Why you don't follow conventions?
You should create a CurrencyMaster class, don't repeat "currmas" or "currrate" in your column's name. Don't override foreign keys... You code should be like this :
class CurrencyMaster < ActiveRecord::Base
has_many :currency_rate_doms
has_many :currency_rate_convs
end
It's the same in your other classes. Rails use the "convention over configuration principe. It would be better after that.
Welcome to wonderful ruby/rails world.
Related
In my rails 3.2 site I have Users and Communities. When a User creates a new Community I want the User to also automatically become a Member of that Community. Memberships form another model. The relationships are as follows:
User:
has_many :memberships
has_many :communities, :through => :memberships
Community:
has_many :memberships
has_many :users, :through => :memberships
Membership:
belongs_to :user
belongs_to :community
In a nutshell then, how do I create a Membership at the same time as I create a Community using the user_id and membership_id obviously?
Update
Controller action:
def create
#community = Community.new(params[:community])
respond_to do |format|
if #community.save
format.html { redirect_to #community, notice: 'Community was successfully created.' }
format.json { render json: #community, status: :created, location: #community }
else
format.html { render action: "new" }
format.json { render json: #community.errors, status: :unprocessable_entity }
end
end
end
This should work if a user creates a community like this:
user.communities.create
From the Rails guide:
The collection of join models can be managed via the API. For example, if you assign
physician.patients = patients
new join models are created for newly associated objects, and if some are gone their rows are deleted.
The working answer was this:
def create
#community = current_user.communities.create(params[:community])
respond_to do |format|
if #community ...
The problem was using build and then #community.save. This did not save the association. Using .create automatically calls new and save and creates the association.
I am studying Belongs_to association, I have used following models, in that every order belongs to the customer, so I have used belongs_to in order model it giving error while creating order
undefined method `orders' for #
when I use has_many :orders in customer model it works fine, why it
does not work with only belongs_to
Its work with has_many :orders in customer model but not with
has_one : order in customer controller it giving same above error.
thanks in advance.
Model :- order.rb
class Order < ActiveRecord::Base
belongs_to :customer
attr_accessible :order_date, :customer_id
end
Model :- customer.rb
class Customer < ActiveRecord::Base
attr_accessible :name
end
controller :- orders.rb
def create
#customer = Customer.find_by_name(params[:name])
#order = #customer.orders.new(:order_date => params[:orderdate] )
respond_to do |format|
if #order.save
format.html { redirect_to #order, notice: 'Order was successfully created.' }
format.json { render json: #order, status: :created, location: #order }
else
format.html { render action: "new" }
format.json { render json: #order.errors, status: :unprocessable_entity }
end
end
end
Technically, belongs_to will work without a matching has_many or has_one. If, for instance, you say that Order belongs_to :customer, you can call .customer on an Order object, and get a Customer object.
What you can't do is call .orders on a Customer without telling it that it has_many :orders (or .order, in the case of has_one), because that method is created by the has_many declaration.
That said, I can't think of any reason you would ever want to only specify half of a relation. It's a terrible design choice, and you should not do it.
Edit: has_one doesn't create the .collection methods that has_many does. Per the guide:
4.2.1 Methods Added by has_one
When you declare a has_one association, the declaring class
automatically gains four methods related to the association:
association(force_reload = false)
association=(associate)
build_association(attributes = {})
create_association(attributes = {})
You'll note that there's no .new on that list. If you want to add an associated object, you can use customer.build_order(), or customer.order = Order.new().
I've got a rather simple setup here: A Doc model, a Publication model, and an Article model.
doc.rb
class Doc < ActiveRecord::Base
attr_accessible :article_ids,:created_at, :updated_at, :title
has_many :publications, dependent: :destroy
has_many :articles, :through => :publications, :order => 'publications.position'
accepts_nested_attributes_for :articles, allow_destroy: false
accepts_nested_attributes_for :publications, allow_destroy: true
end
publication.rb
class Publication < ActiveRecord::Base
attr_accessible :doc_id, :article_id, :position
belongs_to :doc
belongs_to :article
acts_as_list
end
article.rb
class Article < ActiveRecord::Base
attr_accessible :body, :issue, :name, :page, :image, :article_print, :video, :id
has_many :publications
has_many :docs, :through => :publications
end
The Doc form lets users select and order a number of articles:
...
<% #articles.each do |article| %>
<span class="handle">[drag]</span>
<%= check_box_tag("doc[article_ids][]", article.id, #doc.articles.include?(article), :class => "article_chooser" ) %>
<a id="<%= article.id %>" class="name"><%= article.name %></a>
<% end %>
...
This Coffeescript saves the order on drag:
jQuery ->
$('#sort_articles').sortable(
axis: 'y'
handle: '.handle'
update: ->
$.post($(this).data('update-url'), $(this).sortable('serialize'))
);
And this is the sort method in docs_controller.rb:
def sort
Article.all.each_with_index do |id, index|
Publication.update_all({position: index + 1}, {id: id})
end
render nothing: true
end
I've followed this sortable lists Rails cast and it all works well until I update a Doc record because re-ordering isn't saved on update. I've come to the conclusion that it's because my sortable field is on the association table (i.e., publications), but because of the way the app works it has to be.
I've been doing some research here and found this question whose answer comes close, but because I've got a Coffeescript action saving the record in the first place it doesn't work.
Any help would be excellent, I'm really stuck.
Because I struggled for a long time with this I'm putting my stupidly simple solution here. Hopefully it helps someone else.
It's as simple as deleting the old join table records on update before the changes are saved, i.e.:
docs_controller.rb
def update
#doc = Doc.find(params[:id])
#doc.publications.destroy_all
respond_to do |format|
if #doc.update_attributes(params[:doc])
format.html { redirect_to share_url(#doc) }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: #doc.errors, status: :unprocessable_entity }
end
end
end
Boom.
I have 3 models that are basically nested.
class User < ActiveRecord::Base
attr_accessible :birthday, :name
has_one :advancement, :dependent => :destroy
accepts_nested_attributes_for :advancement
attr_accessible :advancement_attributes
end
class Advancement < ActiveRecord::Base
attr_accessible :user_id, :rank_name
belongs_to :user
has_one :rank, :dependent => :destroy
accepts_nested_attributes_for :_rank
attr_accessible :rank_attributes
end
class Rank < ActiveRecord::Base
attr_accessible :advancement_id, :one_li, :one_pi, :one_date, ...
belongs_to :advancement
end
Here is the controller code I use to create my models.
class UsersController < ApplicationController
def new
#user = User.new
#user.advancement = Advancement.new
#user.advancement.rank = Rank.new
respond_to do |format|
format.html # new.html.erb
end
end
def create
#user = User.new(params[:user])
#user.advancement = Advancement.new
#user.advancement.rank = Rank.new
respond_to do |format|
if #user.save
format.html { redirect_to #user, notice: 'User was successfully created.' }
else
format.html { render action: "new" }
end
end
end
end
In the console I can create relations that work like I would expect. When I try to do this through the browser all of my objects are instantiated, the foreign keys are correct, but if I try to find user.advancement, I get a method missing error. Am I using new or create wrong and if so what should I do? Sorry about the amount of code, but I didnt know any other way to explain it.
To start, in most of your code you reference a "rank" model but the model itself appears to be called "BoyScoutRank". Could this be the issue?
As Thanh pointed out, you have accepts_nested_attributes_for :_rank instead of :rank. You also should not need to create new Advancement and Rank models in your create. The accepts_nested_attributes should handle that for you.
Does the following work (once you fix the :_rank issue):
#user = User.new(params[:user])
The Problem:
I am getting an error message when submitting my form that says:
ActiveModel::MassAssignmentSecurity::Error in AdmissionRecordsController#create
Can't mass-assign protected attributes: admission_record
My Setup:
I am using Rails 3.2.3, with extra gems including Cocoon 1.0.14 and Simple_Form 2.0.2
The View:
My app/views/admission_records/_form.html.haml looks like:
= simple_form_for [#admission, #record] do |f|
= f.simple_fields_for :vital_signs, #record.vital_signs.build do |vs|
= render :partial => "vital_sign_fields", :locals => { :f => vs }
= link_to_add_association "Add Vital Signs", f, :vital_signs
= f.submit
And my app/views/admission_records/_vital_sign_fields.html.haml looks like:
.nested-fields
= f.label :sbp
= f.text_field :sbp
...
= link_to_remove_association "Remove Vital Sign"
What I am basically trying to do is that I have a resource called AdmissionRecord nested within another resource called PatientAdmission (route.rb shown below). I have another resource called VitalSign which I want to be able to create via a nested form (using cocoon and simple_form) when creating the AdmissionRecord
My config/routes.rb file looks like:
resources :patient_admissions do
resources :admission_records
end
The Models:
My app/models/patient_admission.rb looks like:
class PatientAdmission < ActiveRecord::Base
has_many :admission_records, :dependent => :destroy
end
My app/models/admission_record.rb looks like:
class AdmissionRecord < ActiveRecord::Base
belongs_to :patient_admission
has_many :vital_signs, :dependent => :destroy
accepts_nested_attributes_for :vital_signs, :rejects_if => :all_blank, :allow_destroy => true
attr_accessible :vital_signs_attributes
end
And my app/models/vital_sign.rb looks like:
class VitalSign < ActiveRecord::Base
belongs_to :admission_record
attr_accessible # just fields that appear in the form
end
The Controller:
The new and create methods in my AdmissionRecordsController looks like:
before_filter do
#admission = PatientAdmission.find(params[:patient_admission_id])
end
def new
#record = #admission.admission_records.build
end
def create
#record = #admission.admission_records.build(params[:admission_record])
#vital_sign = #record.vital_signs.build(params[:vital_signs])
#vital_sign.save
if #record.save
# Flash success and redirect to the right place
else
# Flash error and render :new
end
end
The Plea:
Please help me find where I'm going wrong. I've googled for hours and have looked at other examples and source code for demo apps such as those found in cocoon_simple_form_demo, but still can't seem to fix this error. If there's any other piece of information needed to debug this problem, please let me know. Thanks!
Okay I just had this problem and fixed it by entering one line of code in the belongs_to model.
# patient_admission.rb
Class PatientAdmission < ActiveRecord::Base
attr_accessible :admission_record_attributes
accepts_nested_attributes_for :admission_record
...
end
Here is another solution to it :)