Seeding translation table that has no model, rails app - ruby-on-rails

I am using the Globalize 3 gem as seen in Ryan Bates railscasts, and everything works fine. I need to know how to seed the data though. Currently, I created a table called monthly_post_translations with the following schema
schema.rb
create_table "monthly_post_translations", :force => true do |t|
t.integer "monthly_post_id"
t.string "locale"
t.text "body"
t.datetime "created_at"
t.datetime "updated_at"
end
I need to add seed data to this table, but it doesn't have a model to interact with, so how do I do it?
Here is my currents seeds.rb that isn't working
seeds.rb
# Monthly Posts
MonthlyPost.delete_all
monthlypost = MonthlyPost.create(:body => "Monthly Post Text")
#Monthly Posts Spanish Translation
monthlytranslation = MonthlyPostTranslation.create(:body => "Spanish Translation of monthly post text",
:monthly_post_id => monthlypost.id,
:locale => "es" )
But the monthly_post_translation table doesn't have a model that I can interact with, so I get the error
uninitialized constant MonthlyPostTranslation
Any thoughts on how I can add this seed data properly?

As from documentation by typing translates :<attribute_name_here> you get generated model named MonthlyPost::Translation. So the answer will be: use instance collection to create or list all translations for entity:
monthlypost = MonthlyPost.create(:body => "Monthly Post Text")
#Monthly Posts Spanish Translation
monthlytranslation = monthlypost.translations.create(:body => "Spanish Translation of monthly post text",
:locale => "es" )

Related

Storing List item details in a database?

So, this may be more of a "Software Engineering" question. But im thinking of a good way at how to store details for a Widget in active record.
Pretend Widget A has a show page, and in that show page we have some accordian style "FAQS" or something to that effect. Within the accordian is a list, with bullet points highlighting different things of how Widget A works, or how to use Widget A.
Since obviously we wouldn't want to make a separate page for each widget, these items would need to be stored somewhere. But we also wouldn't want to make...10, 20 or 30 separate fields in the database for each one of these. So whats the solutions for this?
My first thought is some sort of hash or array, but does rails allow this? Especially if they are long strings per item. Is there a better way?
Or is the proper way to do this is just claim this as a model (like.."faq_item") or something, and then have a reference ID for the Widget it needs to go to? (that way the "faq_item" model/schema would only need a few fields, and can just assigned the reference ID to the Widget it would belong to.
If each widget has only a few "FAQ items" (or "details", as I'll refer to them) and each detail is nothing more than a text string, you could store a widget's details in a serialized array as such:
# models/widget.rb
class Widget < ApplicationRecord
# serialize the `details` attribute as JSON into
# the `details` column on the widgets table
serialize :details, JSON
end
# db/schema.rb
# ...
create_table "widgets", force: :cascade do |t|
t.string "name"
t.text "details"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
# rails console
wid = Widget.create!(
:name =>
'Wideband, Voltage-Feedback Operational Amplifier With Disable',
:details => [
'Flexible supply range: 5-V to 12-V Single Supply, +/- 2.5-V to 5-V Dual Supply',
'Unity-Gain Stable: 500 MHz (G = 1)',
'High Output Current: 190 mA',
'High Slew Rate: 1800 V/us',
'Wideband 5-V Operation: 220 MHz (G = 2)'
])
# => #<Widget ...>
wid.details.first
# => "Flexible supply range: 5-V to 12-V Single Supply, +/- 2.5-V to 5-V Dual Supply"
You can look at the Rails 5 serialization API for more information on serialize.
If, however, you need to store more information for each detail (for instance, created_at/updated_at fields) or each widget has more than a few details, then it may be prudent to create a new table for widget details as you suggested:
# models/widget.rb
class Widget < ApplicationRecord
has_many :details, :dependent => :destroy
end
# models/widget/detail.rb
class Widget::Detail < ApplicationRecord
belongs_to :widget
end
# db/schema.rb
# ...
create_table "widget_details", force: :cascade do |t|
t.integer "widget_id"
t.text "content"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
wid = Widget.create!(
:name =>
'CMOS, 125 MHz Complete DDS Synthesizer',
:details => [
Widget::Detail.create!(:content => '125 MHz Clock Rate'),
Widget::Detail.create!(:content => 'On-Chip High Performance DAC'),
Widget::Detail.create!(:content => '32-Bit Frequency Tuning Word')
])
# => #<Widget ...>
wid.details.first
# => #<Widget::Detail ... content: "125 MHz Clock Rate" ...>
If you are using Postgres you could use a JSONB type field in your database. With a JSONB data type you will be able to have unstructured data while being able to query the field with Postgres and ActiveRecord without the need for a new table.
Like this:
rails g migration add_fields_to_widgets details:jsonb
rails db:migrate
Test your widget creation inside the rails console.
Widget.create(name: "Widget Foo", details: { "how to use": "Instructions on how to use", "height": "12cm", "width": "100cm" })
If you'd want to find all the widgets with 12cm height, you would just have to make a query like this:
Widget.where("details->>'height' = ?", "12cm")
which would return your original Widget Foo object, and then you would be able to manipulate it with pure JavaScript on your front-end.

Importing info into existing table Rails

I'm trying to import CSV data into an already existing Rails table.
My CSV has columns of lec_exam, location, meeting_days, begin_time, and end_time. My table looks as follows:
create_table "courses", force: true do |t|
t.string "lec_exam"
t.string "location"
t.string "meeting_days"
t.time "begin_time"
t.time "end_time"
t.datetime "created_at"
t.datetime "updated_at"
t.string "status"
end
The status (i.e. taken vs open) field is something I want to update based on the current time versus the presence of a course occurring at that time.
Every time I import the CSV data the last column (end_time) does not get properly imported because each course has an end_time of nil, when a simple glance at the CSV shows otherwise.
I have tried
CSV.foreach(file.path, headers: true) do |row|
#course_hash = row.to_hash # exclude the price field
#course = Course.where(id: course_hash["id"])
row = Course.create!({
:lec_exam => row[0],
:location => row[1],
:meeting_days => row[2],
:begin_time => row[3],
:end_time => row[4]
})
as well as the to_hash method. Any help towards a solution would be great. Thanks!
To import a CSV data into an existing Rails table add:
require 'csv'
csv_text = File.read('...')
csv = CSV.parse(csv_text, :headers => true)
csv.each do |row|
Moulding.create!(row.to_hash)
end
In the rake task, or in a controller action.
Source: Ruby on Rails - Import Data from a CSV file
Hope this helps!
Solved.
Model had an unneccessary
attr_accessor:
tag. Bleh.

Additional Attributes Appearing in Rails Request Params

I've been seeing some functionality in my rails app whereby the parameters I pass through to rails are being encapsulated somewhere between the request and params in the controller.
It hasn't mattered before but I recently had an issue around this and so decided to try and find out why it was happening. I haven't had any luck and am hoping someone here can point me in the right direction.
My client request payload looks like this:
{
"id"=>"1",
"email" => "peter.hamilton10#imperial.ac.uk",
"first_name" => "Peter",
"last_name" => "Hamilton",
"year" => 3,
"private_attr" => "something"
}
And in rails, the logs show this
Started PUT "/students/1" for 127.0.0.1 at 2012-11-29 13:20:56 +0000
Processing by StudentsController#update as JSON
Parameters: {"id"=>"1",
"email" => "peter.hamilton10#imperial.ac.uk",
"first_name" => "Peter",
"last_name" => "Hamilton",
"year" => 3,
"private_attr" => "something",
"student" => {
"email"=>"peter.hamilton10#imperial.ac.uk",
"first_name"=>"Peter",
"last_name" => "Hamilton",
"year"=>3
}
}
Where is this student attribute coming from and how are it's fields generated?
I know attributes which can't be mass assigned don't appear (illustrated above by private_attr) so I assume its extracting fields for the model for the current controller but otherwise I'm slightly at a loss...
UPDATE: Model
# Schema
# create_table "students" do |t|
# t.string "email"
# t.string "first_name"
# t.string "last_name"
# t.integer "year"
# t.integer "private_attr"
# end
class Student < ActiveRecord::Base
attr_accessible :email, :first_name, :last_name, :year
end
(NOTE: I don't expect private_attr to come through, I just did it as a test and thought it might be useful)
The request isn't actually coming from a form, it's coming from an ajax request generated manually.
Have a look at wrapped parameters:
http://edgeapi.rubyonrails.org/classes/ActionController/ParamsWrapper.html
I don't know if you're using Rails 4 or not but this is the latest version of what is happening under the hood.
In controller add following code:
wrap_parameters :model, include: Model.column_names + [:attr]
Model - your model, :attr - additional attribute

How do I get only unique results from two dissimilar arrays?

This might seem like a duplicate question, but I can't find any information on this. I want to show the results from a remotely acquired json array excluding certain results by comparing them to a local table. I have a gallery model with:
t.integer :smugmug_id
t.string :smugmug_key
t.integer :category_id
t.string :category_name
t.string :description
t.integer :highlight_id
t.string :highlight_key
t.string :highlight_type
t.string :keywords
t.string :nicename
t.integer :subcategory_id
t.string :subcategory_name
t.string :title
t.string :url
The data for this model gets populated by a rake task that connects to the smugmug api (json) and stores the data locally. I'm trying to create a view that shows all the smugmug galleries that are not stored locally.
Here's what I've tried so far, but it's not excluding the locally stored galleries like I thought it would.
def self.not_stored
smugmug_list = Smug::Client.new.albums(heavy = true)
gallery_list = Gallery.select(:smugmug_id)
smugmug_list.each do |smugmug|
smugmug unless gallery_list.include? smugmug.id
end
end
Hopefully this makes sense. I'm getting a json array of galleries, and I want to display that array excluding results where the album id matches the smugmug_id of any of my locally stored records.
Quick edit: I'm using an adaptation of this gem to connect to the smugmug api.
Just use the difference operator.
General Example:
ruby-1.9.2-p136 :001 > [3,2,1] - [2,1]
=> [3]
So you would have:
smugmug_list.collect{|e| e.id} - gallery_list
Enumerable#collect will turn the smugmug_list into a list of id's. From there, you can do the difference operator, which will return all the id's of all the smugmug galleries that are not stored locally.
Another option to maintain the list of galleries:
smugmug_list.select{|e|!gallery_list.include?(e.id)}

globalize2 problem

I have strange globalize2 problem. I'm trying to use globalize 2 and acts_as_textiled and acts_as_commentable. For example - lets we have Post model, that acts_as_commentable. From console
p = Post.find 1
c = p.comments.find 1
works fine, but in browser - nothing displayed
Similar, when Post contains
acts_as_textiled :body
from console body is containing correct data, but in browser i see nothing :(
Any ideas how to correct it?
Upd: "nothing displayed" means,
that for code like
class Post < ActiveRecord::Base
translates :title, :body
acts_as_textiled :body
end
on access to Post.body i've got nil, but on disabled globalize2 or
acts_as_textiled body returns his value. I've tried with different
locales - the same result.
Have you performed the necessary migrations? For localised content you should remove the localised fields in the main table (posts) and create a table for the localisations, like this:
create_table "post_translations", :force => true do |t|
t.string "locale"
t.integer "product_id"
t.string "title"
t.text "body"
end
Just guessing here :)

Resources