So I replaced CKEditor with ActionText in my rails 6 application, the upgrade to rails 6 and installation of action text was smooth.
I want to ask how I can be able to migrate the data from my model attribute to the newly established action text association (well not exactly migrate, I want to be able to display the old data and even be able to edit/update it).
For example, I have a description attribute in my model that was used with CKEditor before, now I have changed that field to a rich_text field like this: has_rich_text :description
So now all references to description simply query its rich_text association.
If I wanted to do something like this in my view, how can I achieve that?
#model.description (display if rich_text data is present) || #model.description (or try this if rich_text data is blank, also display nothing if both is blank)
I'd like to achieve this for show, edit, update and delete actions. Any idea how to make this work?
Why not just migrate the Ckeditor columns to the the new action_text table?
class ConvertCkeditorToActionText < ActiveRecord::Migration[6.0]
def up
action_text_rich_text_statement = ActiveRecord::Base.connection.raw_connection.prepare('action_text_rich_text_statement', <<-SQL)
INSERT INTO action_text_rich_texts (
name, body, record_type, record_id, created_at, updated_at
) VALUES ($1, $2, $3, $4, $5, $6)
SQL
Rails.application.eager_load!
transaction do
Post.all.each do |post|
ActiveRecord::Base.connection.raw_connection.exec_prepared(
'action_text_rich_text_statement', [
'body',
post.body,
"Post",
post.id,
post.created_at,
post.updated_at
])
end
end
end
def down
raise ActiveRecord::IrreversibleMigration
end
end
Related
I am using
ruby version 2.2.6
rails version 4.1.16
postgresql 11.10
gem json-1.8.6
Currently I am getting the error "typeerror: no implicit conversion of hash into string" when I am trying to save a model. This only happen for param that is using json datatype.
The database schema for the table:
create_table "jasons", force: :cascade do |t|
t.string "name"
t.json "description"
end
I already entered accessors for using json in the Jason.rb model like this.
class Jason < ApplicationRecord
:description, accessors: [:key1, :key2, :watapak]
end
and also whitelisted the params in the controller.
def jason_params
params.require(:jason).permit(:name, :description, :key1, :key2, :watapak)
end
and I can call new on the model successfully with
jason = Jason.new(name: "Jason John", key1: "abcd", key2: "efgh")
=> #<Jason id: nil, name: "Jason John", description: {"key1"=>"abcd", "ke...
then when I'm trying to call jason.save, it return's the error "typeerror: no implicit conversion of hash into string".
I tested the code on another environment, using the latest ruby 3.0 and rails 6.1 and everything works great without any error.
One thing that I notice is that the SQL command on both environment is different.
Rails 6.1
Jason Create (0.5ms) INSERT INTO "jasons" ("name", "description") VALUES (?, ?) [["name", "Jason John"], ["description", "\"--- !ruby/hash:ActiveSupport::HashWithIndifferentAccess\\nkey1: abcd\\nkey2: efgh\\n\""]]
Rails 4.1.6
SQL (6.6ms) INSERT INTO "device_models" ("created_at", “name", "description", “updated_at") VALUES ($1, $2, $3, $4) RETURNING "id" [["“created at", "2021-08-09 07:13:04.157826"], ["name", “Jason John"], ["description", "{\"key1\":\"abcd\",\"key2\":\"efgh\"}"], ["updated at", "2021-08-09 07:13:04.157826"]]
The full error is as in this image. Also it differs a bit with the question but the root of the problem is the same.
Do tell me if more information is needed. Also sorry if my question is gibberish as this is my first time posting question, I don't really know how to structure it to make it simpler to understand.
Please help T.T
I suspect that you may have intend to write store :description, accessors: [:key1, :key2, :watapak] which is a hack to store serialized data in a VARCHAR/TEXT columns and does not work with native JSON types. Both serialize and store are practically obsolete.
NOTE: If you are using structured database data types (e.g. PostgreSQL
hstore/json, or MySQL 5.7+ json) there is no need for the
serialization provided by .store. Simply use .store_accessor instead
to generate the accessor methods. Be aware that these columns use a
string keyed hash and do not allow access using a symbol.
class Jason < ApplicationRecord
store_accessor :description, :key1, :key2, :watapak
end
I am working on a rails app, and I added a table. On that table, I wanted an index so to add one, I made a migration for adding a unique index. My migration looks like
class AddIndexToTable < ActiveRecord::Migration
def change
add_index :table, :user_id, unique: true
end
end
everything seemed fine, but now when I run my specs against my migration changes I now get the error
ActiveRecord::RecordNotUnique:
PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_table_name_on_user_id"
DETAIL: Key (user_id)=(15) already exists.
: INSERT INTO "table_name" ("user_id", "day", "last_visited_on", "daily_rewards", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5, $6) RETURNING "id"
I have tried dropping the DB's, re-migrating, re-setting the pk_sequence with ActiveRecord::Base.connection.reset_pk_sequence!(table_name) and other fixes I could find, but I am still stuck on the same error.
Could anyone help me understand why I keep getting this error, and how it can be fixed? I can post more code if needed
You've got either a factory or a test that's trying to create multiple table records for the same user. Either that's going to be obvious looking in the test that's causing this, or perhaps it's an integration test and you don't have your test environment set up properly to clean out the DB between test cases.
For me it was the error that was I allowing the id in the controller params and that I had and let! create ... run at every test. So it tried to create again with the same id.
Removing id from allowed params fixed it.
Well this is a first. I'm trying to run a migration for my Rails app (v4.2.0), and while the migration is succeeding, it's not actually changing anything. Specifically, I'm trying to implement a counter_cache field for a table, assigning the start value for records that already have associations.
Here's my migration:
class AddCommentsCountToQuestions < ActiveRecord::Migration
def up
# dump SQL to console so I can see what's going on
ActiveRecord::Base.logger = Logger.new(STDOUT)
add_column :questions, :comments_count, :integer, null: false, default: 0
Question.reset_column_information
Question.find_each do |question|
puts "updating record #{question.id} to have #{question.comments.count} comments"
# use update! instead of update so that migration performs rollback on failure
question.update!(comments_count: question.comments.count)
puts "record #{question.id} actually persisted with #{question.reload.comments_count} comments"
end
end
def down
remove_column :questions, :comments_count
end
end
My console output demonstrates that upon reloading the record, it didn't persist the comments_count value:
updating record 1 to have 8 comments
record 1 actually persisted with 0 comments
updating record 2 to have 0 comments
record 2 actually persisted with 0 comments
updating record 3 to have 0 comments
And lastly, you can see that the SQL UPDATE command is not doing anything other than changing the updated_at column on the first record (with 8 comments), despite passing a comments_count value in my attributes hash:
D, [2015-02-13T09:15:54.997805 #68245] DEBUG -- : SQL (0.3ms) UPDATE "questions" SET "updated_at" = $1 WHERE "questions"."id" = $2 [["updated_at", "2015-02-13 16:15:54.992779"], ["id", 1]]
I'm making sure to call reset_column_information prior to updating any records, but it seems to have no effect. I've done this plenty of times in recent past (the past few days even) and am banging my head against the wall here.
I'm not sure why your version fails - it looks fine. Still, you might want to try the canonical version of populating counters:
Question.reset_counters(question.id, :comments)
in place of of update!
I was following this railscast, and finished the tutorial. Everything was working fine. Then I decided to use hstore instead of a serialized hash, and after setting up hstore, ran into a error:
PG::Error: ERROR: Syntax error near '!' at position 4 : INSERT INTO "products" ("product_type_id", "created_at", "properties", "updated_at") VALUES ($1, $2, $3, $4) RETURNING "id"
I googled, and found a similar SO question, but I'm using Rails 4, which supposedly doesn't need to use that gem anymore.
Here's my code:
The relevant portion of my form.html.haml looks like this
= f.fields_for :properties, OpenStruct.new(#product.properties) do |builder|
- #product.product_type.products.each do |product|
= render "products/fields/#{product.field_type}", field: field, f: builder
My Product model looks like this:
class Product < ActiveRecord::Base
belongs_to :product_type
serialize :properties
end
I can post more code if it will help. Thanks!
The Rails4 PostgreSQL driver for ActiveRecord is supposed to have native support for PostgreSQL's hstore type so you shouldn't need to use serialize at all. Try ditching the serialize.
BTW, a ! will appear in a YAML string when you attempt to serialize some objects to YAML:
"--- !ruby/object:SomeClassName ..."
and that ! could cause some problems if PostgreSQL was expecting to see an hstore string.
here is what I am trying to do: Find if anyone has tweeted about a specific course offered. If someone has indeed tweeted about it, I'd like to save that tweet to my Tweet Model and then display that tweet in the corresponding course page.
The scripts works locally by running rails runner get_tweets.rb but on Heroku it seems that the script gets executed but doesn't write to the database. In heroku I am running heroku run rails runner get_tweets.rb (using the Cedar stack).
def get_course_tweets
#courses = Course.all
#courses.each do |course|
url = course.url
tweets = Twitter.search(url, {:rpp => 100, :recent => true, :show_user => true})
tweets.each do |tweet_info|
unless Tweet.find_by_tweet_id(tweet_info.id).present?
tweet = Tweet.new
tweet.course_id = course.id
tweet.tweet_id = tweet_info.id
tweet.tweet_text = tweet_info.text
tweet.from_user = tweet_info.from_user
begin
tweet.save!
rescue => error
puts error
end
end
end
end
end
Edit:
The current error I get from rescue is the following:
PG::Error: ERROR: value "186306985577299969" is out of range for type integer : INSERT INTO "tweets" ("book_id", "course_id", "created_at", "from_user", "tutorial_id", "tweet_already_exists", "tweet_id", "tweet_posted_to_reviews", "tweet_text", "updated_at") VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10) RETURNING "id"
As can be seen from your error
value "186306985577299969" is out of range for type integer
you need to use a different datatype (for tweet_id, I believe), presumably a BIGINT, which ranges from -9223372036854775808 to 9223372036854775807.
To do so in Rails you can pass :limit => 8 in your up migration:
change_column :tweets, :tweet_id, :integer, :limit => 8
Note that you should always do some sort of logging or reporting when you rescue, or else bugs like this become very difficult to track down because they silently get bypassed.
The Twitter API actually sends back two types of ID's for tweets and users etc., one is a number, where as the other is a string representation of the number. This is because it's a very real possibility that they will have so many tweets and users that the ID's can overflow in different implementations. If you use the String as your value when inserting it shouldn't happen anymore.
The field is called id_str