LINUX.ORG.RU

Охапка нубских вопросов при разработке проекта c помощью RoR

 ,


0

1

Делаю один проект, зашел в тупик. есть куча вопросов, а гугл не колется. поетому решил упростить задачу

создал новый ресурс следующей коммандой

rails generate scaffold Person name:string phone:string notes:text personrole:references

получил следующую модель

class Person < ActiveRecord::Base                                               
  belongs_to :personrole                                                        
  attr_accessible :name, :notes, :phone                                         
end

пытаюсь в консольке поигратся

irb(main):031:0* p4 = Person.new({:name => 'vasja', :phone => '123456'})
=> #<Person id: nil, name: "vasja", phone: "123456", notes: nil, personrole_id: nil, created_at: nil, updated_at: nil>
irb(main):032:0> p4.save
   (0.3ms)  SAVEPOINT active_record_1
  Person Exists (0.3ms)  SELECT 1 AS one FROM `people` WHERE (`people`.`phone` = BINARY '123456' AND `people`.`name` = 'vasja') LIMIT 1
   (0.3ms)  ROLLBACK TO SAVEPOINT active_record_1
=> false
irb(main):033:0> Person.find(:all)
  Person Load (0.7ms)  SELECT `people`.* FROM `people` 
=> []
irb(main):034:0> 

Пока только два (дальше будет больше и заковырыстие) вопроса

  • почему «false»/Person Exists ?
  • откуда взялся BINARY
★★★★★
Ответ на: комментарий от ZuBB

после следующего

p5 = Person.new({:name => 'vasja', :phone => '123456', :personrole_id => 1})

я получаю такой эрор

ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: personrole_id

я то понимаю что не так, но почему тогда модель(я прав?) так криво генерится?

и да, в attr_accessible нужно добавить personrole или personrole_id?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

и да, в attr_accessible нужно добавить personrole или personrole_id?

так лучше не делать, потому что если у тебя юзеры регаются самостоятельно, то какой-нить Егор Хомяков отправит запрос добавив туда personrole_id=1 и станет админом

Mr_Gentoo
()
Ответ на: комментарий от anonymous

да, вы правы, но не помогает

	from script/rails:6:in `<main>'irb(main):046:0> p5 = Person.new(:name => 'vasja', :phone => '123456', :personrole_id => 1)
ActiveModel::MassAssignmentSecurity::Error: Can't mass-assign protected attributes: personrole_id
	from /var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/mass_assignment_security/sanitizer.rb:48:in `process_removed_attributes'
	from /var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/mass_assignment_security/sanitizer.rb:20:in `debug_protected_attribute_removal'
	from /var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/mass_assignment_security/sanitizer.rb:12:in `sanitize'
	from /var/lib/gems/1.9.1/gems/activemodel-3.2.9/lib/active_model/mass_assignment_security.rb:230:in `sanitize_for_mass_assignment'
	from /var/lib/gems/1.9.1/gems/activerecord-3.2.9/lib/active_record/attribute_assignment.rb:75:in `assign_attributes'
	from /var/lib/gems/1.9.1/gems/activerecord-3.2.9/lib/active_record/base.rb:497:in `initialize'
	from (irb):46:in `new'
	from (irb):46
	from /var/lib/gems/1.9.1/gems/railties-3.2.9/lib/rails/commands/console.rb:47:in `start'
	from /var/lib/gems/1.9.1/gems/railties-3.2.9/lib/rails/commands/console.rb:8:in `start'
	from /var/lib/gems/1.9.1/gems/railties-3.2.9/lib/rails/commands.rb:41:in `<top (required)>'
	from script/rails:6:in `require'
	from script/rails:6:in `<main>'
irb(main):047:0> 

и да, в attr_accessible нужно добавить personrole или personrole_id?

и да, куда(attr_accessible не канает) и что (personrole_id не помогает) нужно добавить?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

модель сейчас

class Person < ActiveRecord::Base                                               
  has_one :personrole                                                           
 attr_accessible :name, :notes, :phone, :personrole                             
end
ZuBB ★★★★★
() автор топика
Ответ на: комментарий от Mr_Gentoo

у меня нет админа и регалки, но тем не менее возможную проблему понимаю

как нужно правильно делать?

ZuBB ★★★★★
() автор топика
Последнее исправление: ZuBB (всего исправлений: 1)
Ответ на: комментарий от Mr_Gentoo

ладно, проехали. у меня своя специфика. регалки нет, роли для «внешних» «пользователей». сисмемных ролей нет (она все одна, ибо будет юзатся одним человеком)

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от kelyar

а оно обновится общесистемно или для моего пользователя?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от kelyar

Gemfile

Gemfile или Gemfile.lock? и кстати а для чего 2й? ибо как раз в нем и есть строчка о activerecord

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от kelyar

понял, еще раз спасибо за обьяснения.

еще один вопрос

  <div class="field">                                                           
    <%= f.label :personrole %><br />                                            
    <%= f.select :personrole,                                                   
        PersonRole.find(:all).collect { |p| [ p.name, p.id ] },                 
        {:prompt => 'Select Person'}                                            
    %>                                                                          
  </div>   

а во вьюхе как быть? оно плюется и на одно и на другое.

а вообще можешь обьяснить (или ссылку дать) откуда пошла такая путаница? это мой завтык или общая лажа?

ZuBB ★★★★★
() автор топика
Последнее исправление: ZuBB (всего исправлений: 1)
Ответ на: комментарий от ZuBB

лучше запрос так делать:

PersonRole.where(name: given_name)

а то PersonRole.find(:all) выберет все записи, а потом будет в памяти ими ворочать. в твоем случае это некритично, но лучше сразу написать правильно

и вроде .find(:all) уже deprecated хотя могу ошибаться, кошерней PersonRole.all, видимо ты по старой книжке учишь

Mr_Gentoo
()
Ответ на: комментарий от Mr_Gentoo

если в обох случаях personrole_id то такое

uninitialized constant Person::PersonroleId

Rails.root: /home/vv/work/own/ruby/reard
Application Trace | Framework Trace | Full Trace

app/controllers/people_controller.rb:43:in `new'
app/controllers/people_controller.rb:43:in `create
ZuBB ★★★★★
() автор топика
Ответ на: комментарий от Mr_Gentoo

выберет все записи

так мне и нужно. + их там пара штук

и вроде .find(:all) уже deprecated хотя могу ошибаться, кошерней PersonRole.all

тоже видел all. Заменил

видимо ты по старой книжке учишь

http://guides.rubyonrails.org

ZuBB ★★★★★
() автор топика

может быть корректно было бы

p5 = Person.new(:name => 'vasja', :phone => '123456')
p5.personrole=Personrole.find something
p5.save
или еще лучше
Personrole.find(id).person.build :name => 'vasja', :phone => '123456'

blan4
()
Ответ на: комментарий от ZuBB

название ты выбрал корявое) надо было или просто role или уже person_role.

там, где label - там вроде все равно, без _id даже лучше. там, где select - там должно быть personrole_id. но давно не делал, точно не помню.

kelyar ★★★★★
()
Ответ на: комментарий от kelyar

Model
person_role

The model is named using the class naming convention of unbroken MixedCase and is always the singular of the table name, e.g. table name might be orders, the model name would be Order. Rails will then look for the class definition in a file called order.rb in the /app/models directory. If the model class name has multiple capitalised words, the table name is assumed to have underscores between these words.

1я ссылка в гугле по ruby model naming convention

там, где label - там вроде все равно

да, так и есть. оно важно только для client side

там, где select - там должно быть personrole_id. но давно не делал, точно не помню.

не пашет.. ошибка таже что и выше

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

person_role
1я ссылка в гугле по ruby model naming convention
unbroken MixedCase

так поздно уже.

personrole:references

сам же написал без underscore, теперь мучайся) если бы написал person_role:references, то и модель бы создало PersonRole

kelyar ★★★★★
()
Ответ на: комментарий от kelyar

так поздно уже.

не понял

personrole:references

сам же написал без underscore, теперь мучайся) если бы написал person_role:references, то и модель бы создало PersonRole

модель PersonRole была создана мной до того как я создал Person

vv@vv-Latitude-E5520 ~/work/own/ruby/reard $ history | grep  Person
44099  rails generate scaffold PersonRole name:string
44111  rails generate scaffold Person name:string phone:string notes:text personrole:references
44147  rails generate scaffold Person name:string phone:string notes:text personrole:references
44171  history | grep  Person
vv@vv-Latitude-E5520 ~/work/own/ruby/reard $ 

ты серьезно думаешь что дело в «_»?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

аа, вроде понял. позже попробуюю.

ZuBB ★★★★★
() автор топика

Если ты играешься именно new+save, то проще все это делать одним create.

ты серьезно думаешь что дело в «_»?

В Rails convention over configuration. Если не будешь следить за именами, потом боком вылезет.

cdshines ★★★★★
()
Ответ на: комментарий от cdshines

cdshines, kelyar: переделал как вы советовали. но в итоге все равно не могу сохратить instance Person`а.

если вы не против, начнем все «с начала»

создал ресурс следующей коммандой

rails generate scaffold Person name:string phone:string notes:text person_role:references

получил следующую модель

class Person < ActiveRecord::Base                                               
  belongs_to :person_role                                                          
  attr_accessible :name, :notes, :phone                                         
end

сделал

rake db:migrate

получил новую таблицу в db/schema.rb

  create_table "people", :force => true do |t|
    t.string   "name"
    t.string   "phone"
    t.text     "notes"
    t.integer  "person_role_id"
    t.datetime "created_at",     :null => false
    t.datetime "updated_at",     :null => false
  end

  add_index "people", ["person_role_id"], :name => "index_people_on_person_role_id"

в консольке сделал Person.new() и получил

irb(main):013:0> p2 = Person.new(:name => 'vasja', :phone => '123456')
=> #<Person id: nil, name: "vasja", phone: "123456", notes: nil, person_role_id: nil, created_at: nil, updated_at: nil>
irb(main):014:0> 

Вопрос: почему в модели person_role а в остальных местах person_role_id?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

http://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefin...

#references will add an appropriately-named _id column

Грубо говоря, это межклассовое отношение belongs_to, насколько я понял, поэтому у тебя для каждой строки в БД (для каждого экземпляра класса в терминах orm) есть поле, указывающее, какому именно объекту belongs эта твоя person.

Если это я правильно понял, то тебе нужно при создании нового объекта явно указывать, какому именно объекту из PersonRole соответствует эта твоя новая запись. По-моему, ты что-то не то намутил с иерархией классов. Расскажи подробнее.

Если я не прав, то пусть руби-боги меня поправят, мне тоже интересно.

олсо, я говорил делать не new+save, a create, если нет разницы

cdshines ★★★★★
()
Ответ на: комментарий от cdshines

вроде все понял, а есть сомнения ибо в голове уже каша

иерархия классов

модель PersonRole

class PersonRole < ActiveRecord::Base                                           
  attr_accessible :name                                                         
  validates :name, :uniqueness => { :case_sensitive => false }                  
  belongs_to :person                                                            
end

в базе

mysql> select * from person_roles;
+----+--------------------------+---------------------+---------------------+
| id | name                     | created_at          | updated_at          |
+----+--------------------------+---------------------+---------------------+
|  1 | співробітник             | 2013-01-24 01:20:02 | 2013-01-24 01:20:02 |
|  2 | клієнт                   | 2013-01-24 01:20:11 | 2013-01-24 01:20:11 |
|  3 | конкурент                | 2013-01-24 01:20:21 | 2013-01-24 01:20:21 |
+----+--------------------------+---------------------+---------------------+
3 rows in set (0.00 sec)

модель Person

class Person < ActiveRecord::Base                                               
  has_one :person_role                                                          
  attr_accessible :name, :notes, :phone                                         
end

belongs_to (изначальное значение после scaffold`а) изменил на has_one.

еще раз вопрос: мне непонятно почему в описании модели person_role а в консольке person_role_id? если в модели должно быть person_role_id, то получается что scaffold работает не правильно? или все таки я где то начудил/не дочитал?

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от cdshines

CanCan is an authorization library for Ruby on Rails

да нет у меня регистрации и тучи пользователей которые приходят и пользуют апп.

апом пользуется 1 (один!) человек. роли используются для людей которых он заносит в базу

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от ZuBB

еще раз вопрос: мне непонятно почему в описании модели person_role а в консольке person_role_id

когда ты пишешь в модельке belongs_to :person_role, то :person_role - это имя ассоциации, которое потом будет мапиться на название класса. поэтому _id тут не нужно, это не название поля.

а в консоле ты смотришь на обьект класса Person и видишь у него person_role_id - это аттрибут и поле в бд.

что сейчас не работает - не сохраняется обьект ручками или не работает скаффолдная вьюшка?

kelyar ★★★★★
()
Ответ на: комментарий от kelyar

и то и другое. сейчас читаю это но голова уже наверно не варит

ps:

class Person < ActiveRecord::Base                                               
  has_one :person_role                                                          
  attr_accessible :name, :notes, :phone                                         
                                                                                
  validates :name, :phone, :presence => true                                    
 #validates_associated :person_role_id                                          
                                                                                
  validates :phone, :length => { :minimum => 5 },                               
                    :uniqueness => {:scope => :name},                           
                    :numericality => {:only_integer => true}                    
end

    <%= f.select :person_role_id,                                               
        PersonRole.all.collect { |p| [ p.name, p.id ] },                        
        {:prompt => 'Select Person'}                                            
    %>                                                                          
  </div>

ошибка: Can't mass-assign protected attributes: person_role_id

ZuBB ★★★★★
() автор топика
Ответ на: комментарий от kelyar

работает. еще раз спасибо

есть 3 вопроса:

  • та ссылка говорит о возможных проблемах с безопасностью. а так можно делать?
  • судя по всему у вас много опыта :) посоветуйте чтото еще кроме http://guides.rubyonrails.org/
  • вам можна еще задавать множество нубских вопросов?
ZuBB ★★★★★
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.