I have a tables with content in two languages. Then I have a column called 'language' to distinguish.Now I use I18n to do multi languages website.So, how can I get content in database with current language?
I think that if I can set the default_scope of model accoding to the language, or load different models the same name.
Thank you!
You can use a URL parameter to set the application locale for a request, for example:
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
before_action :set_locale
def set_locale
I18n.locale = params[:locale] || I18n.default_locale
end
end
Find the model by current locale:
YourContent.where(name: some_name, language: I18n.locale)
and use the t method in views with your strings files since you have the application locale set.
The docs have a few other examples.
Yes, you can use default_scope { language: I18n.locale } to omit the extra where, but be aware of the caveats of default_scope.
If you want to switch to different table conditionally for same model, you can use ActiveRecord::Base.table_name class method.
Example:
cTable4 ❯ rails c -e production
Running via Spring preloader in process 60375
Loading production environment (Rails 4.2.4)
irb(main):001:0> Book.first
Book Load (0.1ms) SELECT "books".* FROM "books" ORDER BY "books"."id" ASC LIMIT 1
=> #<Book id: 1, name: "ELoquent Ruby", author: "Russ", year: "2011", created_at: "2016-01-07 08:40:47", updated_at: "2016-01-07 08:40:47">
irb(main):002:0> Book.table_name = 'titles'
=> "titles"
irb(main):003:0> Book.first
Book Load (0.2ms) SELECT "titles".* FROM "titles" ORDER BY "titles"."id" ASC LIMIT 1
=> #<Book id: 1, title: "Practical OOD Ruby", author: "Sandi Metz">
irb(main):004:0>
Related
I have created a Ruby on Rails job (extending from ActiveJob::Base) that parses a CSV file and inserts its rows as records (Students) in a database. That is working as expected.
However, when I try to fetch another object from the DB (the Career for each Student, which is part of each CSV row as a pair (career_code, career_name)), I'm getting this error:
undefined method 'find_by' for Career:Class
(I have also tried using Career.where instead).
I find this quite strange, since I'm already saving my Student, which is also an ActiveRecord::Base child class.
Here's the relevant part of my job:
ActiveRecord::Base.transaction do
student_hash.keys.each do |k|
some_student = student_hash[k]
student = Student.new
student.csv_id = some_student.id
student.first_name = some_student.first_name
student.last_name = some_student.last_name
student.file_number = some_student.file_number
# student.career = Career.where(code: some_student.career_code)
student.career = Career.find_by code: some_student.career_code
puts student.save! # Why this works, and the above line doesn't?
end
end
And also, the desired output, as I can see it in the Rails console:
Loading development environment (Rails 4.2.4.rc1)
2.1.3 :001 > Career.where(code: 11)
Career Load (0.5ms) SELECT "careers".* FROM "careers" WHERE "careers"."code" = ? [["code", 11]]
=> #<ActiveRecord::Relation [#<Career id: 4, name: "Informática", created_at: "2015-09-30 22:05:07", updated_at: "2015-09-30 22:05:07", code: 11>]>
2.1.3 :002 > Career.where code: 11
Career Load (0.2ms) SELECT "careers".* FROM "careers" WHERE "careers"."code" = ? [["code", 11]]
=> #<ActiveRecord::Relation [#<Career id: 4, name: "Informática", created_at: "2015-09-30 22:05:07", updated_at: "2015-09-30 22:05:07", code: 11>]>
2.1.3 :003 > Career.find_by code: 11
Career Load (0.4ms) SELECT "careers".* FROM "careers" WHERE "careers"."code" = ? LIMIT 1 [["code", 11]]
=> #<Career id: 4, name: "Informática", created_at: "2015-09-30 22:05:07", updated_at: "2015-09-30 22:05:07", code: 11>
2.1.3 :004 >
Probably this is a really stupid question, but I'm quite a beginner using Rails. Do I need to import some sort of "Context" (this seems unlikely, since Student seems to be properly resolved)? I'm using Rails 4.2.4.rc1 by the way.
Thanks in advance
Any chance at that point in the code Career isn't an AR, but some other class? That would at least explain why the methods don't exist.
I have an attribute in my model that is stored as text but interpreted as a rational. I have this method to handle that:
def start
read_attribute(:start).to_r
end
When I set the start attribute to a new value, the start_was helper method returns a string, instead of a rational, but before I do so, it returns the correct value. Why?
Loading development environment (Rails 3.2.8)
1.9.3p194 :001 > d = Day.find(55)
Day Load (8.7ms) SELECT "days".* FROM "days" WHERE "days"."id" = ? LIMIT 1 [["id", 55]]
=> #<Day id: 55, date: "2012-03-30", start: "1/2", finish: "2/2", created_at: "2012-09-18 15:16:42", updated_at: "2012-09-19 08:20:41", day_year_id: 1>
1.9.3p194 :002 > d.start_was
=> (1/2)
1.9.3p194 :003 > d.start=0
=> 0
1.9.3p194 :004 > d.start_was
=> "1/2"
I think the reason is this method in ActiveModel (activemodel-3.2.8\lib\active_model\dirty.rb)
# Handle <tt>*_was</tt> for +method_missing+.
def attribute_was(attr)
attribute_changed?(attr) ? changed_attributes[attr] : __send__(attr)
end
As you see, if attribute was not actually changed it just calls its own getter, in your case hitting your start method which does the transformation. But if the attribute is actually changed, it reads its raw value from the changed_attributes storage.
UPDATE:
If the after_validation callback is used, it works as desired (e.g. the false value is persistent). Still would like to know why that is, but I guess this is solved for my purposes :)
For a boolean field, I would like a callback in the model to set the default value to false instead of nil.
Currently when I create a new record, it initially shows the value as false, but then shows it as nil.
Wondering what's going on here and if the desired behavior is possible w/ a callback.
This is in the model:
after_save :default_is_forsale
def default_is_forsale
self.not_for_sale = false if self.not_for_sale.nil?
end
Here is the rails console output (irrelevant bits omitted):
1.9.3p125 :001 > Item.create(name: "thing 4")
(0.1ms) begin transaction
SQL (6.4ms) INSERT INTO items [...]
(190.8ms) commit transaction
=> #<Item id: 20, name: "thing 4", not_for_sale: false>
Cool, created the new record with a default value of false. But when I check again:
1.9.3p125 :002 > Item.last
Item Load (0.3ms) SELECT [...]
=> #<Item id: 20, name: "thing 4", not_for_sale: nil>
Weird, now the value is nil.
But if I create a new record and explicitly set the value to false, it acts as I'd expect:
1.9.3p125 :003 > Item.create(name: "more thing", not_for_sale: false)
(0.1ms) begin transaction
SQL (0.7ms) INSERT INTO items [...]
(225.2ms) commit transaction
=> #<Item id: 21, name: "more thing", not_for_sale: false>
When retrieved, the record still shows its boolean value of false
1.9.3p125 :004 > Item.last
Item Load (0.3ms) SELECT [...]
=> #<Item id: 21, name: "more thing", not_for_sale: false>
BTW, I read elsewhere that the desired result is achievable via db migrations, but I am new to rails and would like to accomplish it through the model.
Thanks
Change your migration to set this boolean to false, as default. if there was code i'd show you.
I just read you were 'new to rails' but that doesn't matter. You don't need to do it in the model, unless you want that record to be true.
You want this in a before_save callback. The after_save callback is called, unsurprisingly, after the record has already been saved.
It appears some of my seeds are not saving. For starters, I will show a console session so you can see that the 'instructor_id' is indeed being set in the console, but not when I seed.
ruby-1.9.2-p180 :015 > c = Course.find 2
Course Load (1.6ms) SELECT "courses".* FROM "courses" WHERE "courses"."id" = $1 LIMIT 1 [["id", 2]]
=> #<Course id: 2, name: "Microcomputers II Lab", course_code: "CE-420L", instructor_id: nil, school_id: nil, created_at: "2011-06-04 19:40:32", updated_at: "2011-06-04 19:40:32">
ruby-1.9.2-p180 :016 > c.instructor = Instructor.first
Instructor Load (0.6ms) SELECT "instructors".* FROM "instructors" LIMIT 1
=> #<Instructor id: 1, name: "Instructor Name", created_at: "2011-06-04 19:40:32", updated_at: "2011-06-04 19:40:32">
ruby-1.9.2-p180 :017 > c
=> #<Course id: 2, name: "Microcomputers II Lab", course_code: "CE-420L", instructor_id: 1, school_id: nil, created_at: "2011-06-04 19:40:32", updated_at: "2011-06-04 19:40:32">
From looking at the console, you can see that when I call c.instructor = Instructor.first, it is correctly setting my instructor_id.
Now, in the seeds file I have variables. (This is just a snippet)
### Instructors ###
puts "Creating Instructors"
instructor_1 = Instructor.find_or_create_by_name("Instructor Name")
### Courses ###
puts "Creating Courses"
ce420L = Course.find_or_create_by_name("Microcomputers II Lab", :course_code => "CE-420L")
### Add the Instructor to the Course ###
puts "Adding an Instructor to the Courses"
ce420L.instructor = instructor_1
But when I run the seeds using 'rake db:seed', it is correctly creating all of my models, and most of my relationships. But it is not setting the instructor properly.
Thoughts?
EDIT:
Just tried:
ce420 = Course.find_or_initialize_by_name("Microcomputers II")
ce420.instructor_id = instructor_1.id
ce420.save!
And it did not save my instructor.
Here are my models.
class Instructor < ActiveRecord::Base
### ASSOCIATIONS ###
has_many :courses
end
class Course < ActiveRecord::Base
belongs_to :instructor
end
Did you run...
ce420L.save!
... after assigning the instructor?
Much faster to do this:
### Courses ###
puts "Creating Courses belonging to Instructor 1"
ce420L = Course.find_or_initialize_by_name("Microcomputers II Lab") :course_code => "CE-420L")
ce420L.instructor_id = instructor_1.id
ce420L.save
Note the following:
You had an errant comma after your find_or_create on ce420L.
Doing the assignment together with the course creation prevents the system from validating and saving ce420L twice.
You can try assigning the specific ID as I did, i.e. ce420L.instructor_id = ...
If this doesn't work, check your Instructor Model to ensure you don't have any callbacks getting in the way.
There is model Ratification with attribute comment (of type text)
def Ratification < ActiveRecord::Base
attr_accessor :add_comment
def add_comment=(text)
self.comment ||= ""
self.comment << "\r\n" + text
end
end
And if I use add_comment= it is ok before I save the object. After save comment changes was dropped.
>> r = Ratification.last
Ratification Load (0.6ms) SELECT * FROM `ratifications` ORDER BY ratifications.id DESC LIMIT 1
=> #<Ratification id: 8, user_id: 686, comment: "dasads", created_at: "2010-06-25 13:16:24", updated_at: "2010-06-25 13:38:36">
>> r.comment
=> "dasads"
>> r.add_comment="text"
=> "text"
>> r.comment
=> "dasads\r\ntext"
>> r.save
SQL (0.7ms) BEGIN
SQL (0.2ms) COMMIT
=> true
>> r.reload
Ratification Load (1.6ms) SELECT * FROM `ratifications` WHERE (`ratifications`.`id` = 8)
=> #<Ratification id: 8, user_id: 686, comment: "dasads", created_at: "2010-06-25 13:16:24", updated_at: "2010-06-25 13:38:36">
>> r.comment
=> "dasads"
Why?!
Rails 2.3.8
Ruby 1.8
Hrrrm...that IS weird, I'm seeing similar behavior from my rails app when I try to do:
#s.name << "test"
and then reload...the original name is getting reset!
HOWEVER, if I do #s.name += "test"
then even after reloading, the new name is saved.
I'm not sure why << is behaving like that, but I usually default to += in all cases, so I've never noticed it before. Does changing to += help you?
Edit: Looking at the API, maybe it's because << modifies the original string, whereas + or += makes a NEW string, that contains the old one? Maybe rails somehow only saves things that it has marked as new (rather than modified?)