accepts_nested_attributes - ActiveRecord::UnknownAttributeError - ruby-on-rails

I have a very simple model that each event has many forexes. I am trying to create a nested form to create new event with a bunch of forexes in a go.
class Event < ActiveRecord::Base
has_many :forexes
accepts_nested_attributes_for :forexes
end
class Forex < ActiveRecord::Base
belongs_to :event
end
The schema is like this:
ActiveRecord::Schema.define(version: 20180505093823) do
create_table "events", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "base"
end
create_table "forexes", force: :cascade do |t|
t.string "code"
t.float "rate"
t.integer "event_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "forexes", ["event_id"], name: "index_forexes_on_event_id"
end
And then I tried to create new objects using the following code in rails console. It fails.
Event.new( name: "11", base: "HKD", forexes_attributes: [ {code: "RMB", rate:1}, {code: "CNY",rate:2}])
It throws me back with this error.
ActiveRecord::UnknownAttributeError: unknown attribute 'forexes_attributes' for Event.
I know this is quite a basic question. And I have tried many different ways after researching in different places. I couldn't debug it. Appreciate your help.

In your Event controller you need to include the forexes_attributes in event_params method as along with default one
def event_params
params.require(:event).permit(forexes_attributes: Forexes_attribute_names.map(&:to_sym).push(:_destroy))
end

Related

Ransack: Conditions on both a child, and its respective grandchild record

Don't be intimidated by the length. It's probably actually quite simple.I couldn't find an answer, though I tried looking everywhere. I hope this is a good enough challenge for you.
Here goes:
Panel.rb
has_many :status_dates
has_many :statuses, through: :status_dates
StatusDate.rb
belongs_to :status
belongs_to :panel
def self.ransackable_attributes(auth_object = nil)
%w( current ) + _ransackers.keys
end
Status.rb
has_many :status_dates
Here is the schema.
create_table "panels", force: :cascade do |t|
t.string "no"
t.integer "project_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "status_dates", force: :cascade do |t|
t.integer "status_id"
t.integer "panel_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.date "date"
t.boolean "current"
end
add_index "status_dates", ["panel_id"], name: "index_status_dates_on_panel_id"
add_index "status_dates", ["status_id"], name: "index_status_dates_on_status_id"
create_table "statuses", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
What do I want to do?
I want to identify a parent record based on two conditions which must both simultaneously exist exist on: (i) a child record and (ii) in turn, that child's, child record too (i.e. a grand child record).
What does that mean?
Suppose we have:
I want to find all panels, where there is a particular StatusDate record such that StatusDate.current = y, and its respective child, Status.name = x.
(“Current” is actually a boolean value on the StatusDate record.)
What is happening at the moment?
Here is my _condition_fields.html.erb partial:
What is the problem?
Right now, ransack applies those conditions across different records. But I want them applied directly to: (I) a child record and (ii) that particular child's child record as well.
Any idea how I can do this?
Assistance very much appreciated.
Did you try query following way:
Panel.ransack({StatusDate_current:0, StatusDate_Status_name: "Installed"})

Rails - collection_select does not select a values from tables having translations

I am relatively new to RoR.
This works nicely:
<td><%= collection_select :competitions_members, :member_id, Member.all, :id, :first_name %></td>
This one picks no value (actually all such calls to tables with translations):
<td><%= collection_select :competitions_members, :tull_id, Tull.all, :id, :name %></td>
seeded data in competitions_members table
Member can be involved in many competition. Basically I have N:M relationship between members and competitions via competitions_members table.
Tull is a dictionary. Value to be set during the process of assigning members to a competition.
Data model classes:
class Member < ApplicationRecord
has_and_belongs_to_many :competitions
end
class Competition < ApplicationRecord
has_and_belongs_to_many :members
end
class CompetitionsMember < ApplicationRecord
end
Tull table has also translations in separate table.
class Tull < ApplicationRecord
translates :name
has_many :competitions_members
# separate different localizations of the record
def cache_key
super + '-' + Globalize.locale.to_s
end
end
Relevant schema.db excerpt
create_table "members", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "competitions", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
create_table "competitions_members", force: :cascade do |t|
t.integer "member_id"
t.integer "competition_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "tull_id"
t.index ["tull_id"], name: "index_competitions_members_on_tull_id"
end
create_table "tull_translations", force: :cascade do |t|
t.integer "tull_id", null: false
t.string "locale", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.string "name"
t.index ["locale"], name: "index_tull_translations_on_locale"
t.index ["tull_id"], name: "index_tull_translations_on_tull_id"
end
create_table "tulls", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
Any help apreciated. I just realized this might be connected with translated tables somehow.
class Tull < ApplicationRecord
has_many :translations
translates :name, :fallbacks_for_empty_translations => true
attr_accessible :translations_attributes
end
Try to execute below code in rails console:
Tull.first.translations - If this gives you translation records that means the associations are correct.
Now check at view side, how would you generate attributes for multilingual stuffs. I would suggest to use globalize_accessors.
Please send me the codebase.

How would I go about allowing users to create surveys

Iv'e gotten myself into a bit of a brain mess up these past two days. I'd like to be able to allow my users to create a campaign (same concept as surveys), it will allow them to request certain data they wish such as an email address. This will then allow the person completing the form to proceed and receive a download link after entering an email. The email entered should be stored for the person who created the campaign to view.
Iv'e taken the approach with nested forms, however I ran into the trouble of allowing emails to be entered and saved for the campaign creator to view.
Any help is appreciated, thanks.
campaign.rb model
class Campaign < ActiveRecord::Base
belongs_to :user
has_many :queries
accepts_nested_attributes_for :queries
end
query.rb model
class Query < ActiveRecord::Base
belongs_to :campaign
has_many :results
end
result.rb model
class Result < ActiveRecord::Base
attr_accessible :content, :email, :query_id
belongs_to :query
end
schema.rb
create_table "campaigns", force: :cascade do |t|
t.string "title"
t.text "description"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "campaigns", ["user_id"], name: "index_campaigns_on_user_id", using: :btree
create_table "queries", force: :cascade do |t|
t.integer "campaign_id"
t.text "content"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "queries", ["campaign_id"], name: "index_queries_on_campaign_id", using: :btree
create_table "results", force: :cascade do |t|
t.integer "query_id"
t.text "content"
t.string "email"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "results", ["query_id"], name: "index_results_on_query_id", using: :btree
Part of campaign_controller.rb
private
# Use callbacks to share common setup or constraints between actions.
def set_campaign
#campaign = Campaign.find(params[:id])
end
def campaign_params
params.require(:campaign).permit(:title, :description, :queries_attributes)
end
def query_params
params.require(:query).permit(:content, :email, :campaign_id)
end

Test in Rails console model associations?

Hello I do have this two models and I would like to check that my model associations are working the way it should trough rails console.
I am not able to do the association work. The relationship is the following:
One Event has one rule and one rule belongs to one event. It could not be a rule without an event and it could not be a event without a rule.
Any idea how to test this with rails console?
MODEL 1:
class Event < ActiveRecord::Base
has_and_belongs_to_many :users
has_one :rule
has_many :grand_prixes
belongs_to :eventable, polymorphic: :true
end
MODEL 2
class Rule < ActiveRecord::Base
belongs_to :events
end
Rules' Schema:
create_table "rules", force: :cascade do |t|
t.boolean "abs"
t.boolean "tc"
t.boolean "allow_auto_clutch"
t.boolean "allow_sc"
t.boolean "allow_throttle_blip"
t.boolean "dynamic_track"
t.integer "damage_mult"
t.integer "fuel_rate"
t.integer "tyre_wear_rate"
t.integer "quali_percentage"
t.integer "min_valid_laps"
t.integer "event_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "rules", ["event_id"], name: "index_rules_on_event_id"
Events' Schema:
create_table "events", force: :cascade do |t|
t.string "event_type"
t.string "name", null: false
t.datetime "starting_date"
t.datetime "ending_date"
t.integer "eventable_id"
t.string "eventable_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "events", ["eventable_type", "eventable_id"], name: "index_events_on_eventable_type_and_eventable_id"
Thanks in advance.
I think your belongs_to :events should be singular to follow the rails convention :
class Rule < ActiveRecord::Base
belongs_to :event
end
The conventional name of a relation is always singular for belongs_to and has_one, and always plural for has_many.
Related documentation : http://guides.rubyonrails.org/association_basics.html#belongs-to-association-reference
EDIT : There much left to say
You wrote :
ev = Event.create(:name "test1").save
rule = Rule.create.save
create is already a new followed by a save. No need to save afterwards.
the syntax key: value is something very common in ruby, and should be well understood : you're actually writing a hash, equivalent to {:key => value}, but the syntax allows you to write key: value ONLY IF your key is a Symbol.
the columns eventable_type and eventable_id should be in the table rules, who is hosting the polymorphic relation with eventable things. Event should not have these columns, and event_id should not exist at all in rules.
Here's an example of what you can write in your console to create an Event and a Rule :
ev = Event.create(name: "test1")
rule = Rule.create(abs: true, event: ev)
Change your code:
class Rule < ActiveRecord::Base
belongs_to :event
end
With belongs_to you should use singular like event not events.
In console you can check association like:
Event.first.rule if Event.first.present?
For more details you should go through http://guides.rubyonrails.org/association_basics.html documentation.
Current code:
class Rule < ActiveRecord::Base
belongs_to :event
end
class Event < ActiveRecord::Base
has_and_belongs_to_many :users
has_one :rule
has_many :grand_prixes
belongs_to :eventable, polymorphic: :true
end
SCHEMA:
create_table "rules", force: :cascade do |t|
t.boolean "abs"
t.boolean "tc"
t.boolean "allow_auto_clutch"
t.boolean "allow_sc"
t.boolean "allow_throttle_blip"
t.boolean "dynamic_track"
t.integer "damage_mult"
t.integer "fuel_rate"
t.integer "tyre_wear_rate"
t.integer "quali_percentage"
t.integer "min_valid_laps"
t.integer "event_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "rules", ["event_id"], name: "index_rules_on_event_id", unique: true
create_table "events", force: :cascade do |t|
t.string "event_type"
t.string "name", null: false
t.datetime "starting_date"
t.datetime "ending_date"
t.integer "eventable_id"
t.string "eventable_type"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "events", ["eventable_type", "eventable_id"], name: "index_events_on_eventable_type_and_eventable_id"
Tested on console:
ev = Event.create(:name "test1").save
rule = Rule.create.save
No idea how to link it both through console.

How do I build a complex nested form to represent dynamic attributes

I've got a data model represented by the following image:
Basically, the idea is that there are many different Collections. All the Items in a single collection will have the same Attributes, but the list of attributes will be different per collection. The value of each Attribute per item will be stored in Item Attribute Values.
I'm trying to build a single page where a user can populate the attributes for an item. I'm assuming a nested form is the way to go but I'm at a loss as to how to represent this in the controller and on the page, considering the names of the attributes are in one table and the values in another.
If anyone has encountered or had to deal with a similar situation, any help would be appreciated.
Thanks
Here is one potential solution.
class Collection
has_and_belongs_to_many :items
has_and_belongs_to_many :attributes
end
class Item
has_and_belongs_to_many :collections
has_many :item_attributes
has_many :attributes, though: :item_attributes
end
class Attributes
has_and_belongs_to_many :collections
has_many :item_attributes
has_many :items, though: :item_attributes
end
class ItemAttribute
belongs_to :item
belongs_to :attribute
end
So lets look at the database layout to back these models:
ActiveRecord::Schema.define(version: 20151027173337) do
create_table "attributes_collections", id: false, force: :cascade do |t|
t.integer "attribute_id", null: false
t.integer "collection_id", null: false
end
create_table "collections", force: :cascade do |t|
t.string "title"
t.integer "user_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "collections", ["user_id"], name: "index_collections_on_user_id"
create_table "collections_items", id: false, force: :cascade do |t|
t.integer "collection_id", null: false
t.integer "item_id", null: false
end
create_table "item_attributes", force: :cascade do |t|
t.integer "item_id"
t.integer "attribute_id"
t.string "value"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "item_attributes", ["attribute_id"], name: "index_item_attributes_on_attribute_id"
add_index "item_attributes", ["item_id"], name: "index_item_attributes_on_item_id"
create_table "items", force: :cascade do |t|
t.string "name"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
end
A Better way?
But of course performance will suffer due to the many joins. Plus each attribute will be stored as a VARCHAR which means you can't do any numeric comparisons in the database.
If you really need a flexible schema i would instead look into using HSTORE, JSON or another dynamic column type or a schemaless database such as MongoDB.
How do I create a form / controller for this?
First you should get very acquainted with what can be done with accepts_nested_attributes_for and fields_for and maybe consider using AJAX to delegate the actions out to CollectionController and a ItemController on the back end rather than cramming it all into a single monstrosity.

Resources