I have a Attributes column in one of my model,
and the Attributes column is hstore type, it stores JSON format string,
I want my user to edit it in normal form type,
I wish it could span to 4 input-fields automatically,
name
range
security
default_value
is there any gem to achieve it ?
UPDATE
I followed #zwippie solution, and show it in the form correctly,
But it can not be updated,
When I tried to updated it,
But I should add those fields into strong parameters,
is there any dynamic way, to achieve this.
To expand all the columns in the hstro rather than hard code store_accessor :cgi_attributes, :name, :range, :security, :default_value,
and also append it into white list
= f.text_area column, class: 'input-xxlarge'
But it
Rails 4 can do this out of the box. Add this to your model:
store_accessor :attributes, :name, :range, :security, :default_value
Now you can use the hstore attributes as normal Active Record attributes:
item = Item.find(2)
item.update(security: '5/6')
Or in a form:
<%= f.text_field :default_value %>
I dont think theres a gem to achive it but its still possible using metaprogamming.
Using metaprogramming you can create methods dynamicly based on the data of an object. I explained it here for serialized data which is very likely to your situation.
The thing you need to extend is the view but thats not such a problem you can simpley call a methed that returns all keys of the serialized data and then loop through them and generate inputs.
I guess PostgreSQL hstore might be useful if your are using a postgresql database in your application.
Related
Considering Students who can study various things, I'm storing those in a jsonb column referencing a Studies table. Indexing the studies isn't really important (for now) and I prefer to avoid a relationship table.
Therefore: add_column :students, :studies, :jsonb, default: []
And in my simple form (in slim):
= simple_form_for #student do |f|
= f.input :studies, as: :check_boxes, collection: Study.all, label_method: :name
This works stupendously well considering the brevity and the simplicity of it. Except for one small detail: the form doesn't check previously saved studies as their IDs are stored as strings in the jsonb array ["", "2", "12"] and the form apparently requires integers.
I resorted to add a studies' value function in the Student model, but it seems sooo overkill (also the .reject(&:zero?) to remove the empty array value):
def studies=(array)
# transform strings to integers and remove leading empty value
super(array.map(&:to_i).reject(&:zero?))
end
Is there a better way?
I would say the better way is just using the relationship table. Overriding the assignment method on a model is generally not the right approach.
JSONB is nice, gives flexibility, and can be even queried nicely, but unless you have a really strong reason to go with it in this case, you should probably stick to has_many :through... association.
Either way, depending on how you wired everything, maybe instead of overriding the assignment method you would be better by putting your logic in action filters or somewhere where you do model validation...
I'm currently in the process of switching from ActiveRecord's as_json to RABL for API generation.
as_json has been rendering timestamps in my models as strings of the format 2012-09-16T22:14:11+00:00. However, when I switched to RABL timestamps started rendering as epoch numbers like 1347926218.084763000 (note these dates are from two different objects and are not supposed to be equal). Is there a way to force the string format?
My .rabl template is pretty simple:
object #person
attributes :id, :created_on, :name
and I get:
{"id":3,"created_on":1347926218.084763000,"name":"fred"}
object #person
node(:id){|person|(person.id)}
node(:created_on){|person|(person.created_on.strftime(%d,%m,%Y)}
node(:name){|person|(person.name)}
end
or try
object #person
attributes :id, :name
node(:created_on){|person|(person.created_on.strftime(%d,%m,%Y)}
end
There are more options for .strftime() you can find on many sites. It must be used on a :date object type. You can customize the date output with it's options. I'm working on custom nodes for some json output and am learning this the hard way!
If you need the the attributes in a certain order I'd use the one with nodes because the attributes seem to 'float to the top' of the json object created.
Im using collectiveidea's audited solution for auditing in rails.
So, there's a column (audited_changes) that is a TEXT definition in the database. When i retrieve an audit from the database, i get a plain string, and when i call that attribute in the view is non formated string. In the rdocs it says that theres a serialized hash of all changes. How can i get this hash? Also, in the same docs it says that there's access to old_attributes and new_attributes, how is this?
In my view:
<%= #audit.action %> # => update
<%= #audit.audited_changes %> # => --- name: - oldname - newname code: - oldcode - newcode
Or any chance on formatting this?
I think there might currently be a bug in audited. Are you using 3.0.0rc1? That is what I am using and I had something similar happen. First off, it didn't seem to recognize "Audit" as an ActiveRecord object, so I created an empty model in app/models/audit.rb. Once I did that I was seeing the behaviour you are seeing. To fix it, I removed the app/models/audit.rb and added an config/initializers/audited.rb with this in it:
include Audited::Adapters::ActiveRecord
This is an old question but I have an alternative answer that seems to be working well for me using Rails 4.2. Instead of using the initializer in the above answer I suggest keeping the model and adding "serialize :audited_changes" to the top.
class Audit < ActiveRecord::Base
belongs_to :user
serialize :audited_changes
end
You could use the built-in Audited::Audit model to query its data.
For example,
audit = Audited::Audit.last
audit.audited_changes # => {"name"=>["Steve", "Ryan"]}
"Steve" is the old value, "Ryan" is the new value. By default, the hash is stored in yaml format in the database.
I am using https://github.com/plataformatec/simple_form and am trying to send a extra parameter. I have a Task, List and ListTask models, in the new page of the of the list I want to be able to insert the number of tasks that will be added. When you submit it will send you to the new list_task page with the correct number of forms populated.
=simple_form_for #list do |s|
=s.input :title
=s.input :task_count
=s.button :submit
This produces a error undefined method task_count, which makes sense because it is not a method in list.
if you don't want the value persisting to the db, add a virtual attribute:
class List < ActiveRecord::Base
attr_accessor :task_count
end
this will allow you to use that attribute in the form, but that will only persist for the life of that object but it will make it into your POST params.
...otherwise, if you want it to persist to the db (which is sounds like you may). You'd add task_count as a column in your lists table (via a migration).
I'm trying to do up a rails form_for that includes a checkbox for :terms_and_conditions (with validates_presence_of). terms_and_conditions has not been declared as a column in the corresponding database table.
At the moment, when I submit the form and try to create a new model with MyModel.new(params[:mymodel]), I get an *'unknown attribute: terms_and_conditions'* error.
So, just wondering: how do I run create a field for a column - and run validations on it - without inserting that field into the database?
Many thanks...
You need a virtual attribute for terms_and_conditions in your model.
Take a look at this screencast
For accepting T&Cs only, you should now be able to just put this in your model:
validates_acceptance_of :terms_and_conditions