Beginner here, learning ruby on rails by jumping into a project. This question is probably pure ruby and has nothing to do with rails. I also want to note that I'm using Active_Admin.
I have the following 2 classes: Owner and Phone.
class Owner < ActiveRecord::Base
attr_accessible :email, :password,
has_many :phones
end
class Phone < ActiveRecord::Base
attr_accessible :owner_id :model
belongs_to :owner
end
How would I go accessing the owners email from within the phones model, for example:
form do |f|
f.inputs "Phone Details" do
f.input :model
f.input :owner_id # This is where I want the email, not the owners id.
end
f.buttons
end
It looks like I should review the pickaxe book and refine my ruby before jumping into rails.
Thanks
to have both the owner and the phone in one form, your form should look something like this:
form_for #phone do |phone_form|
phone_form.label :model
phone_form.text_field :model
fields_for #phone.owner do |owner_fields|
owner_fields.label :email
owner_fields.text_field :email
If you use this method, make sure you can update the Owner from the Phone model by setting accepts_nested_attributes_for :owner on you Phone model.
In this case you should use nested form. Usage of nested form is explained very well in this railscast.
Related
I have two models Trip and Attraction for admin panel I have used ActiveAdmin. Now while creating new trip from activeadmin I wished to add user can select multiple Attractions and it's data should be stored in another table called trip_attractions (:trip_id , :attraction_id)
Here is my model:
class Trip < ActiveRecord::Base
has_and_belongs_to :attractions
end
class Attraction < ActiveRecord::Base
has_and_belongs_to_many :trips
end
class TripAttraction < ActiveRecord::Base
has_many :trips
has_many :attractions
end
and for ActiveAdmin form customization I tried in app/admin/trip.rb
ActiveAdmin.register Trip do
.....
form multipart: true do |f|
f.inputs "Trip" do
f.input :title
f.input :description
# Here I want to show all attractions and as multiple select it should be stored in trip_attractions table
f.input 'Attractions' do
f.input :attractions, :as => :select, :multiple => true, collection: Attraction.all
end
end
Where I do mistake? Please guide me how can I show all attractions on new trip form and on multiple select it should be stored in trip_attractions table. I really appreciate for your guideline and help. If you required more details then please feel free to ask.
In addition : I also tried to add attraction_ids field in trip table and in model I defined it as serialize to stored as an array of attraction's ids but I think it's not good approach as attraction may deleted it's id will remain in trip table. So I avoid this option and also not saved in database while submitting form. :(
Imagine I have the following models:
class Translation < ActiveRecord::Base
has_many :localizations
end
class Localization < ActiveRecord::Base
belongs_to :translation
end
If I do this in ActiveAdmin:
ActiveAdmin.register Localization do
form do |f|
f.input :word
f.input :content
end
end
The association for word will only allow me to choose from existing words. However, I'd like to have the option of creating a new word on the fly. I thought it may be useful to accept nested attributes in the localization model ( but then, I will only have the option of creating a Word, not selecting from existing ones ). How can I solve this problem?
I think you can try using virtual attribute for this
Example(not tested)
class Localization < ActiveRecord::Base
attr_accessor :new_word #virtual attribute
attr_accessible :word_id, :content, :new_word
belongs_to :translation
before_save do
unless #new_word.blank?
self.word = Word.create({:name => #new_word})
end
end
end
The main idea is to create and store new Word instance before saving localization and use it instead of word_id from drop-down.
ActiveAdmin.register Localization do
form do |f|
f.input :word
f.input :content
f.input :new_word, :as => :string
end
end
There is great rails-cast about virtual attributes http://railscasts.com/episodes/167-more-on-virtual-attributes
I know that one way to add/edit/delete (nested) records using a form is by using :accepts_nested_attributes_for: in the the corresponding models. However, when this nesting extends to about 4 levels (because of the normalization of the database), and I want to display all of these levels for editing on the website, this method seems to be rather cumbersome (and ugly).
I was wondering whether there is a way to define 'super' models with getter and setter methods that allow me to edit the necessary data in one place . As a simplified example, consider:
class Person < ActiveRecord::Base
attr_accessible :name, :age
has_one :address
end
class Address < ActiveRecord::Base
attr_accessible :street, :zip, :country
belongs_to :person
end
I would like to show/edit/update/etc the name, age, street, zip, country in one form. It's clear how to do this using accepts_nested_attributes_for. But I would like to have a class, say, PersonalInformation, that combines the fields name, age, street, zip, country from both classes by passing in the id from Person. I would then like to use this class as an interface for the website.
Something like a Form Object as described here:
http://robots.thoughtbot.com/activemodel-form-objects
I've been trying various implementations and haven't found the perfect solution but they do simplify "bringing a bunch of models together". The codeclimate blog also touches on it (item #3) at:
http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models
The codeclimate post uses an older method of including the ActiveModel modules (no need to include them individually unless you want to now) but the concept is the same.
I would recommend the simple form gem. I modified an example from their docs to reflect your models that does exactly what you want:
Models:
class Person < ActiveRecord::Base
attr_accessible :name, :age
has_one :address
end
class Address < ActiveRecord::Base
attr_accessible :street, :zip, :country
belongs_to :person
end
View:
<%= simple_form_for #person do |f| %>
<%= f.input :name %>
<%= f.input :age %>
<%= f.association :street %>
<%= f.association :zip %>
<%= f.association :country %>
<%= f.button :submit %>
<% end %>
You could use virtual attributes on the Person model and put custom assignment logic within the getters/setters for each of the editable Address attributes.
class Person < ActiveRecord::Base
attr_accessible :name, :age
has_one :address
def street=(new_street)
# ...
end
end
This would likely end up being more complex in the long run.
So here's the Thing:
I have a Rails App with "Productos" and "Ventas" Both resources have the same attributes on their tables and ventas has one more (quantity)... the models look like this:
#Producto Model
class Producto < ActiveRecord::Base
has_and_belongs_to_many :categorias, :join_table => :categoria_productos
attr_accessible :color, :existencia, :nombre, :precio, :talla, :uniclave, :categoria_ids
#Venta Model
class Venta < ActiveRecord::Base
attr_accessible :cantidad, :color, :nombre, :precio, :talla, :uniclave, :producto_ids
has_many :productos
end
I'm using ActiveAdmin for the Admin interface and my /admin/venta.rb looks like this:
ActiveAdmin.register Venta do
form do |f|
f.inputs "Registrar Venta" do
f.input :cantidad
f.input :productos, :as => :check_boxes
end
f.buttons
end
end
The result is ALL THE PRODUCTOS are showing in the "new venta" form and I can select them, but when I create a new Venta actually, the params of "venta" save empty instead of taking the selected "producto" ones...
How can I fix this?? I want all the params of the selected "producto" to be used in the newly created "venta" fields as they share the same attributes (both models have been created with the same attributes actually)
So, ideas? ;)
:categoria_ids and : producto_ids must be as :categoria_id and :producto_id OR you must use the :foreign_key for behavior between models
I've got a problem with designing my User model and making a decent form for it. I just want to ensure myself that I'm doing it wrong :)
So it goes like this:
User has got two Addresses:
a mandatory Address for identification and billing,
an optional shipping Address that he could fill in or leave blank
I tried like this:
class User < ActiveRecord::Base
has_one :address
has_one :shipping_address, :class_name => 'Address', :foreign_key => 'shipping_address_id'
accepts_nested_attributes_for :address
accepts_nested_attributes_for :shipping_address
#validations for user
end
and:
class Address < ActiveRecord::Base
#validations for address
end
And then I make a form for User using form_for and nested fields_for. Like this:
= form_for #user, :url => '...' do |a|
= f.error_messages
...
= fields_for :address, #user.build_address do |a|
...
But then, despite that f.error_messages generates errors for all models, fields for Addresses don't highlight when wrong.
Also I have problems with disabling validation of the second address when the user chose not to fill it in.
And I have doubts that my approach is correct. I mean the has_one relation and overall design of this contraption.
So the question:
Am I doing it wrong? How would You do that in my place?
What is wrong in your form is that it will build a new address every time the view is rendered, thus losing all validation errors.
In your controller, in the new action you should do something like
#user.build_address
and in your view write:
= fields_for :address, #user.address do |a|
Hope this helps.