From f61b539c1b8af9897f8197d305b6335571f4d28b Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Thu, 29 Mar 2012 14:34:43 +0200 Subject: [PATCH 01/14] =?UTF-8?q?Entrega=205=20Luis=20Mart=C3=ADnez=20Gall?= =?UTF-8?q?ego?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/assets/images/fotocarnet.jpg | Bin 0 -> 75646 bytes app/assets/stylesheets/planet.css | 21 +++++++++++ app/controllers/planet_controller.rb | 11 ++++++ app/controllers/types_controller.rb | 9 +++++ app/views/layouts/application.html.erb | 41 +++++++++++++++++++--- app/views/planet/author.html.erb | 36 +++++++++++++++++++ app/views/types/index.html.erb | 1 + app/views/types/ordered_index.html.erb | 31 ++++++++++++++++ app/views/types/show.html.erb | 8 ++++- config/routes.rb | 7 ++++ test/functional/planet_controller_test.rb | 10 ++++++ 11 files changed, 169 insertions(+), 6 deletions(-) create mode 100644 app/assets/images/fotocarnet.jpg create mode 100644 app/views/planet/author.html.erb create mode 100644 app/views/types/ordered_index.html.erb diff --git a/app/assets/images/fotocarnet.jpg b/app/assets/images/fotocarnet.jpg new file mode 100644 index 0000000000000000000000000000000000000000..7424162f41534a7dbff89eee1e076bd3cfab2be4 GIT binary patch literal 75646 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ɪ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 :name) + + respond_to do |format| + format.html # show.html.erb + format.json { render json: @type } + end + end end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 1ed9716..ce6b6c1 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -14,20 +14,51 @@ + +

+
- <%= link_to "Home", planet_index_path %>
- <%= link_to "Tipos", types_path %>
- <%= link_to "Sitios", sites_path %>
- <%= link_to "Contact", planet_contact_path %> + + <%= link_to "Home", planet_index_path %>
+ <%= link_to "Tipos", types_path %>
+ <%= link_to "Sitios", sites_path %>
+ <%= link_to "Contact", planet_contact_path %> + +
+ + <%= yield %> +
-
+ + + + \ No newline at end of file diff --git a/app/views/planet/author.html.erb b/app/views/planet/author.html.erb new file mode 100644 index 0000000..c3f3a34 --- /dev/null +++ b/app/views/planet/author.html.erb @@ -0,0 +1,36 @@ +

Datos Personales Del Autor

+ + +
+<%= image_tag('fotocarnet.jpg')%> + +
    +
  • Nombre: Luis Martínez Gallego
  • +
  • Dirección: C/Castelao nº 5 5º-A
    Pontevedra(Galicia) España
    36001
  • +
  • Email: luismg87@gmail.com
  • + +
+
+ +
+

Curriculum Vitae

+ +

Formación

+ +
    +
  • 2003 : Título de grado en Educación Secundaria Obligatoria por el instituto Los +Sauces.
  • +
  • 2005: Título de bachiller por el instituto Los Sauces.
  • +
  • Desde 2005 estudiante de Ingeniería en Telecomunicaciones en la universidad +Politécnica de Madrid , realizando actualmente PFC y asignaturas 4º curso.
  • +
+

Idiomas

+
    +
  • Español: Nativo
  • +
  • Gallego: Nativo
  • +
  • Inglés: B2
  • +
  • Aleman: B1
  • +
+ +
+ diff --git a/app/views/types/index.html.erb b/app/views/types/index.html.erb index e761359..31f503a 100644 --- a/app/views/types/index.html.erb +++ b/app/views/types/index.html.erb @@ -10,6 +10,7 @@
<%= link_to type.name, type_sites_path(type) %>
<%= truncate(strip_tags(type.description), :length => 80) %>
+
Fecha última actualización : <%= type.updated_at %>
diff --git a/app/views/types/ordered_index.html.erb b/app/views/types/ordered_index.html.erb new file mode 100644 index 0000000..31f503a --- /dev/null +++ b/app/views/types/ordered_index.html.erb @@ -0,0 +1,31 @@ +
+

Listing Types

+ + + <% @types.each do |type| %> + + + + + + + <% end %> +
+
+
<%= link_to type.name, type_sites_path(type) %>
+
<%= truncate(strip_tags(type.description), + :length => 80) %>
+
Fecha última actualización : <%= type.updated_at %>
+
+
+ <%= link_to 'Show', type %>
+ <%= link_to 'Edit', edit_type_path(type) %>
+ <%= link_to 'Destroy', type, + :confirm => 'Are you sure?', + :method => :delete %> +
+
+ +
+ +<%= link_to 'New Type', new_type_path %> diff --git a/app/views/types/show.html.erb b/app/views/types/show.html.erb index 98b32e7..b159302 100644 --- a/app/views/types/show.html.erb +++ b/app/views/types/show.html.erb @@ -2,7 +2,8 @@

Name: - <%= @type.name %> + <%= @type.name %> +

@@ -10,6 +11,11 @@ <%= @type.description %>

+

+Fecha última actualización : +<%= @type.updated_at %> +

+ <%= link_to 'Edit', edit_type_path(@type) %> | <%= link_to 'Back', types_path %> diff --git a/config/routes.rb b/config/routes.rb index 716dc7e..a5db786 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,6 +1,9 @@ Planet::Application.routes.draw do + resources :sites + get "types/ordered_index" + resources :types do # Rutas anidadas /types/id/sites..., resources :sites, :only => [ :index ] # Restringe a acción “index” end @@ -11,6 +14,10 @@ get "planet/ejemplo" + get "planet/author" + + + # The priority is based upon order of creation: # first created -> highest priority. diff --git a/test/functional/planet_controller_test.rb b/test/functional/planet_controller_test.rb index 88229e0..10fe5ad 100644 --- a/test/functional/planet_controller_test.rb +++ b/test/functional/planet_controller_test.rb @@ -11,4 +11,14 @@ class PlanetControllerTest < ActionController::TestCase assert_response :success end + test "should get ejemplo" do + get :ejemplo + assert_response :success + end + + test "should get author" do + get :author + assert_response :success + end + end From cd3b34d9c1f786338c751c64544cd7f2bb61663c Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Sun, 15 Apr 2012 17:58:25 +0200 Subject: [PATCH 02/14] validaciones y test corregidos --- app/models/site.rb | 8 ++++++++ app/models/type.rb | 5 +++++ test/fixtures/types.yml | 3 +++ test/functional/planet_controller_test.rb | 10 ---------- test/functional/types_controller_test.rb | 8 ++++++-- test/unit/site_test.rb | 10 ++++++++++ test/unit/type_test.rb | 8 ++++++++ 7 files changed, 40 insertions(+), 12 deletions(-) diff --git a/app/models/site.rb b/app/models/site.rb index 3eb288d..31f4370 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -1,3 +1,11 @@ class Site < ActiveRecord::Base belongs_to :type + + + + # Debe estar protegido para evitar accesos indeseados + + + # Se añaden estas definiciones + validates :name, :type_id,:image_url, :presence => true # campo obligatorio end diff --git a/app/models/type.rb b/app/models/type.rb index 7c3d2ac..2284d1f 100644 --- a/app/models/type.rb +++ b/app/models/type.rb @@ -1,3 +1,8 @@ class Type < ActiveRecord::Base has_many :sites + + + # Se añade esta definición de recurso + validates :name, :description, :presence => true # campo obligatorio + validates :name, :uniqueness => true # Campo único (no repetido) end diff --git a/test/fixtures/types.yml b/test/fixtures/types.yml index 53b2c6a..8683ea9 100644 --- a/test/fixtures/types.yml +++ b/test/fixtures/types.yml @@ -7,3 +7,6 @@ one: two: name: MyString description: MyText + + +# Podriamos añadir nuevos datos de inicialización, que se referencian como # -> types(:monumento) types(:naturaleza) monumento: name: Monumento description: “Edificio o construcción de valor historico” naturaleza: name: Naturaleza description: “Lugar al aire libre de interés natural” \ No newline at end of file diff --git a/test/functional/planet_controller_test.rb b/test/functional/planet_controller_test.rb index 10fe5ad..88229e0 100644 --- a/test/functional/planet_controller_test.rb +++ b/test/functional/planet_controller_test.rb @@ -11,14 +11,4 @@ class PlanetControllerTest < ActionController::TestCase assert_response :success end - test "should get ejemplo" do - get :ejemplo - assert_response :success - end - - test "should get author" do - get :author - assert_response :success - end - end diff --git a/test/functional/types_controller_test.rb b/test/functional/types_controller_test.rb index 2e1931b..d8b0dc1 100644 --- a/test/functional/types_controller_test.rb +++ b/test/functional/types_controller_test.rb @@ -3,6 +3,10 @@ class TypesControllerTest < ActionController::TestCase setup do @type = types(:one) + @update = { # @update: parametros diferentes + :name => 'AnotherType', + :description => 'AnotherText', + } end test "should get index" do @@ -18,7 +22,7 @@ class TypesControllerTest < ActionController::TestCase test "should create type" do assert_difference('Type.count') do - post :create, type: @type.attributes + post :create, type: @update end assert_redirected_to type_path(assigns(:type)) @@ -35,7 +39,7 @@ class TypesControllerTest < ActionController::TestCase end test "should update type" do - put :update, id: @type, type: @type.attributes + put :update, id: @type, type: @update assert_redirected_to type_path(assigns(:type)) end diff --git a/test/unit/site_test.rb b/test/unit/site_test.rb index 38c8dd0..34931c1 100644 --- a/test/unit/site_test.rb +++ b/test/unit/site_test.rb @@ -4,4 +4,14 @@ class SiteTest < ActiveSupport::TestCase # test "the truth" do # assert true # end + + # site creado sin atributos es invalido y genera errores + test "Site attributes must not be empty" do + site = Site.new + assert site.invalid? # Test pasa si validación no pasa + assert site.errors[:name].any? + assert not(site.errors[:description].any?) + assert site.errors[:type_id].any? + assert site.errors[:image_url].any? + end end diff --git a/test/unit/type_test.rb b/test/unit/type_test.rb index 0ce1172..7c92595 100644 --- a/test/unit/type_test.rb +++ b/test/unit/type_test.rb @@ -4,4 +4,12 @@ class TypeTest < ActiveSupport::TestCase # test "the truth" do # assert true # end + + # type creado sin atributos es invalido y genera errores + test "Type attributes must not be empty" do + type = Type.new + assert type.invalid? # Test pasa si validación no pasa + assert type.errors[:name].any? + assert type.errors[:description].any? + end end From 91c7d5c06e988598f1d2b7feb8838551b5e2afc3 Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Sun, 15 Apr 2012 18:04:58 +0200 Subject: [PATCH 03/14] instalar devise,user y nombre --- Gemfile | 2 + Gemfile.lock | 10 + app/models/user.rb | 11 + config/initializers/devise.rb | 223 ++++++++++++++++++ config/locales/devise.en.yml | 57 +++++ config/routes.rb | 2 + .../20120415155937_devise_create_users.rb | 49 ++++ db/migrate/20120415160149_user_name.rb | 13 + db/schema.rb | 21 +- test/fixtures/users.yml | 11 + test/unit/user_test.rb | 7 + 11 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 app/models/user.rb create mode 100644 config/initializers/devise.rb create mode 100644 config/locales/devise.en.yml create mode 100644 db/migrate/20120415155937_devise_create_users.rb create mode 100644 db/migrate/20120415160149_user_name.rb create mode 100644 test/fixtures/users.yml create mode 100644 test/unit/user_test.rb diff --git a/Gemfile b/Gemfile index 7764763..7231379 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,8 @@ gem 'rails', '3.2.2' gem 'sqlite3' +gem 'devise' + # Gems used only for assets and not required # in production environments by default. diff --git a/Gemfile.lock b/Gemfile.lock index 81a3ba7..b16d2d9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -29,6 +29,7 @@ GEM i18n (~> 0.6) multi_json (~> 1.0) arel (3.0.2) + bcrypt-ruby (3.0.1) builder (3.0.0) coffee-rails (3.2.2) coffee-script (>= 2.2.0) @@ -37,6 +38,11 @@ GEM coffee-script-source execjs coffee-script-source (1.2.0) + devise (2.0.4) + bcrypt-ruby (~> 3.0) + orm_adapter (~> 0.0.3) + railties (~> 3.1) + warden (~> 1.1.1) erubis (2.7.0) execjs (1.3.0) multi_json (~> 1.0) @@ -53,6 +59,7 @@ GEM treetop (~> 1.4.8) mime-types (1.17.2) multi_json (1.1.0) + orm_adapter (0.0.7) polyglot (0.3.3) rack (1.4.1) rack-cache (1.2) @@ -98,12 +105,15 @@ GEM uglifier (1.2.3) execjs (>= 0.3.0) multi_json (>= 1.0.2) + warden (1.1.1) + rack (>= 1.0) PLATFORMS ruby DEPENDENCIES coffee-rails (~> 3.2.1) + devise jquery-rails rails (= 3.2.2) sass-rails (~> 3.2.3) diff --git a/app/models/user.rb b/app/models/user.rb new file mode 100644 index 0000000..d6c2cd3 --- /dev/null +++ b/app/models/user.rb @@ -0,0 +1,11 @@ +class User < ActiveRecord::Base + # Include default devise modules. Others available are: + # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable + devise :database_authenticatable, :registerable, + :recoverable, :rememberable, :trackable, :validatable + + validates_presence_of :name + + # Setup accessible (or protected) attributes for your model + attr_accessible :name, :email, :password, :password_confirmation, :remember_me +end diff --git a/config/initializers/devise.rb b/config/initializers/devise.rb new file mode 100644 index 0000000..6e922dc --- /dev/null +++ b/config/initializers/devise.rb @@ -0,0 +1,223 @@ +# Use this hook to configure devise mailer, warden hooks and so forth. +# Many of these configuration options can be set straight in your model. +Devise.setup do |config| + # ==> Mailer Configuration + # Configure the e-mail address which will be shown in Devise::Mailer, + # note that it will be overwritten if you use your own mailer class with default "from" parameter. + config.mailer_sender = "please-change-me-at-config-initializers-devise@example.com" + + # Configure the class responsible to send e-mails. + # config.mailer = "Devise::Mailer" + + # Automatically apply schema changes in tableless databases + config.apply_schema = false + + # ==> ORM configuration + # Load and configure the ORM. Supports :active_record (default) and + # :mongoid (bson_ext recommended) by default. Other ORMs may be + # available as additional gems. + require 'devise/orm/active_record' + + # ==> Configuration for any authentication mechanism + # Configure which keys are used when authenticating a user. The default is + # just :email. You can configure it to use [:username, :subdomain], so for + # authenticating a user, both parameters are required. Remember that those + # parameters are used only when authenticating and not when retrieving from + # session. If you need permissions, you should implement that in a before filter. + # You can also supply a hash where the value is a boolean determining whether + # or not authentication should be aborted when the value is not present. + # config.authentication_keys = [ :email ] + + # Configure parameters from the request object used for authentication. Each entry + # given should be a request method and it will automatically be passed to the + # find_for_authentication method and considered in your model lookup. For instance, + # if you set :request_keys to [:subdomain], :subdomain will be used on authentication. + # The same considerations mentioned for authentication_keys also apply to request_keys. + # config.request_keys = [] + + # Configure which authentication keys should be case-insensitive. + # These keys will be downcased upon creating or modifying a user and when used + # to authenticate or find a user. Default is :email. + config.case_insensitive_keys = [ :email ] + + # Configure which authentication keys should have whitespace stripped. + # These keys will have whitespace before and after removed upon creating or + # modifying a user and when used to authenticate or find a user. Default is :email. + config.strip_whitespace_keys = [ :email ] + + # Tell if authentication through request.params is enabled. True by default. + # It can be set to an array that will enable params authentication only for the + # given strategies, for example, `config.params_authenticatable = [:database]` will + # enable it only for database (email + password) authentication. + # config.params_authenticatable = true + + # Tell if authentication through HTTP Basic Auth is enabled. False by default. + # It can be set to an array that will enable http authentication only for the + # given strategies, for example, `config.http_authenticatable = [:token]` will + # enable it only for token authentication. + # config.http_authenticatable = false + + # If http headers should be returned for AJAX requests. True by default. + # config.http_authenticatable_on_xhr = true + + # The realm used in Http Basic Authentication. "Application" by default. + # config.http_authentication_realm = "Application" + + # It will change confirmation, password recovery and other workflows + # to behave the same regardless if the e-mail provided was right or wrong. + # Does not affect registerable. + # config.paranoid = true + + # By default Devise will store the user in session. You can skip storage for + # :http_auth and :token_auth by adding those symbols to the array below. + # Notice that if you are skipping storage for all authentication paths, you + # may want to disable generating routes to Devise's sessions controller by + # passing :skip => :sessions to `devise_for` in your config/routes.rb + config.skip_session_storage = [:http_auth] + + # ==> Configuration for :database_authenticatable + # For bcrypt, this is the cost for hashing the password and defaults to 10. If + # using other encryptors, it sets how many times you want the password re-encrypted. + # + # Limiting the stretches to just one in testing will increase the performance of + # your test suite dramatically. However, it is STRONGLY RECOMMENDED to not use + # a value less than 10 in other environments. + config.stretches = Rails.env.test? ? 1 : 10 + + # Setup a pepper to generate the encrypted password. + # config.pepper = "b4579c0728e03479c7b2b897815e87ea0ef4117fe5961c19d54c9976d8ddca660a803eb982c351e72665b32ff46d8774a51727467205df158ced37817db4faae" + + # ==> Configuration for :confirmable + # A period that the user is allowed to access the website even without + # confirming his account. For instance, if set to 2.days, the user will be + # able to access the website for two days without confirming his account, + # access will be blocked just in the third day. Default is 0.days, meaning + # the user cannot access the website without confirming his account. + # config.allow_unconfirmed_access_for = 2.days + + # If true, requires any email changes to be confirmed (exctly the same way as + # initial account confirmation) to be applied. Requires additional unconfirmed_email + # db field (see migrations). Until confirmed new email is stored in + # unconfirmed email column, and copied to email column on successful confirmation. + config.reconfirmable = true + + # Defines which key will be used when confirming an account + # config.confirmation_keys = [ :email ] + + # ==> Configuration for :rememberable + # The time the user will be remembered without asking for credentials again. + # config.remember_for = 2.weeks + + # If true, extends the user's remember period when remembered via cookie. + # config.extend_remember_period = false + + # If true, uses the password salt as remember token. This should be turned + # to false if you are not using database authenticatable. + config.use_salt_as_remember_token = true + + # Options to be passed to the created cookie. For instance, you can set + # :secure => true in order to force SSL only cookies. + # config.cookie_options = {} + + # ==> Configuration for :validatable + # Range for password length. Default is 6..128. + # config.password_length = 6..128 + + # Email regex used to validate email formats. It simply asserts that + # an one (and only one) @ exists in the given string. This is mainly + # to give user feedback and not to assert the e-mail validity. + # config.email_regexp = /\A[^@]+@[^@]+\z/ + + # ==> Configuration for :timeoutable + # The time you want to timeout the user session without activity. After this + # time the user will be asked for credentials again. Default is 30 minutes. + # config.timeout_in = 30.minutes + + # ==> Configuration for :lockable + # Defines which strategy will be used to lock an account. + # :failed_attempts = Locks an account after a number of failed attempts to sign in. + # :none = No lock strategy. You should handle locking by yourself. + # config.lock_strategy = :failed_attempts + + # Defines which key will be used when locking and unlocking an account + # config.unlock_keys = [ :email ] + + # Defines which strategy will be used to unlock an account. + # :email = Sends an unlock link to the user email + # :time = Re-enables login after a certain amount of time (see :unlock_in below) + # :both = Enables both strategies + # :none = No unlock strategy. You should handle unlocking by yourself. + # config.unlock_strategy = :both + + # Number of authentication tries before locking an account if lock_strategy + # is failed attempts. + # config.maximum_attempts = 20 + + # Time interval to unlock the account if :time is enabled as unlock_strategy. + # config.unlock_in = 1.hour + + # ==> Configuration for :recoverable + # + # Defines which key will be used when recovering the password for an account + # config.reset_password_keys = [ :email ] + + # Time interval you can reset your password with a reset password key. + # Don't put a too small interval or your users won't have the time to + # change their passwords. + config.reset_password_within = 6.hours + + # ==> Configuration for :encryptable + # Allow you to use another encryption algorithm besides bcrypt (default). You can use + # :sha1, :sha512 or encryptors from others authentication tools as :clearance_sha1, + # :authlogic_sha512 (then you should set stretches above to 20 for default behavior) + # and :restful_authentication_sha1 (then you should set stretches to 10, and copy + # REST_AUTH_SITE_KEY to pepper) + # config.encryptor = :sha512 + + # ==> Configuration for :token_authenticatable + # Defines name of the authentication token params key + # config.token_authentication_key = :auth_token + + # ==> Scopes configuration + # Turn scoped views on. Before rendering "sessions/new", it will first check for + # "users/sessions/new". It's turned off by default because it's slower if you + # are using only default views. + # config.scoped_views = false + + # Configure the default scope given to Warden. By default it's the first + # devise role declared in your routes (usually :user). + # config.default_scope = :user + + # Configure sign_out behavior. + # Sign_out action can be scoped (i.e. /users/sign_out affects only :user scope). + # The default is true, which means any logout action will sign out all active scopes. + # config.sign_out_all_scopes = true + + # ==> Navigation configuration + # Lists the formats that should be treated as navigational. Formats like + # :html, should redirect to the sign in page when the user does not have + # access, but formats like :xml or :json, should return 401. + # + # If you have any extra navigational formats, like :iphone or :mobile, you + # should add them to the navigational formats lists. + # + # The "*/*" below is required to match Internet Explorer requests. + # config.navigational_formats = ["*/*", :html] + + # The default HTTP method used to sign out a resource. Default is :delete. + config.sign_out_via = :delete + + # ==> OmniAuth + # Add a new OmniAuth provider. Check the wiki for more information on setting + # up on your models and hooks. + # config.omniauth :github, 'APP_ID', 'APP_SECRET', :scope => 'user,public_repo' + + # ==> Warden configuration + # If you want to use other strategies, that are not supported by Devise, or + # change the failure app, you can configure them inside the config.warden block. + # + # config.warden do |manager| + # manager.intercept_401 = false + # manager.default_strategies(:scope => :user).unshift :some_external_strategy + # end +end diff --git a/config/locales/devise.en.yml b/config/locales/devise.en.yml new file mode 100644 index 0000000..73df488 --- /dev/null +++ b/config/locales/devise.en.yml @@ -0,0 +1,57 @@ +# Additional translations at https://github.com/plataformatec/devise/wiki/I18n + +en: + errors: + messages: + expired: "has expired, please request a new one" + not_found: "not found" + already_confirmed: "was already confirmed, please try signing in" + not_locked: "was not locked" + not_saved: + one: "1 error prohibited this %{resource} from being saved:" + other: "%{count} errors prohibited this %{resource} from being saved:" + + devise: + failure: + already_authenticated: 'You are already signed in.' + unauthenticated: 'You need to sign in or sign up before continuing.' + unconfirmed: 'You have to confirm your account before continuing.' + locked: 'Your account is locked.' + invalid: 'Invalid email or password.' + invalid_token: 'Invalid authentication token.' + timeout: 'Your session expired, please sign in again to continue.' + inactive: 'Your account was not activated yet.' + sessions: + signed_in: 'Signed in successfully.' + signed_out: 'Signed out successfully.' + passwords: + send_instructions: 'You will receive an email with instructions about how to reset your password in a few minutes.' + updated: 'Your password was changed successfully. You are now signed in.' + updated_not_active: 'Your password was changed successfully.' + send_paranoid_instructions: "If your e-mail exists on our database, you will receive a password recovery link on your e-mail" + confirmations: + send_instructions: 'You will receive an email with instructions about how to confirm your account in a few minutes.' + send_paranoid_instructions: 'If your e-mail exists on our database, you will receive an email with instructions about how to confirm your account in a few minutes.' + confirmed: 'Your account was successfully confirmed. You are now signed in.' + registrations: + signed_up: 'Welcome! You have signed up successfully.' + signed_up_but_unconfirmed: 'A message with a confirmation link has been sent to your email address. Please open the link to activate your account.' + signed_up_but_inactive: 'You have signed up successfully. However, we could not sign you in because your account is not yet activated.' + signed_up_but_locked: 'You have signed up successfully. However, we could not sign you in because your account is locked.' + updated: 'You updated your account successfully.' + update_needs_confirmation: "You updated your account successfully, but we need to verify your new email address. Please check your email and click on the confirm link to finalize confirming your new email address." + destroyed: 'Bye! Your account was successfully cancelled. We hope to see you again soon.' + unlocks: + send_instructions: 'You will receive an email with instructions about how to unlock your account in a few minutes.' + unlocked: 'Your account has been unlocked successfully. Please sign in to continue.' + send_paranoid_instructions: 'If your account exists, you will receive an email with instructions about how to unlock it in a few minutes.' + omniauth_callbacks: + success: 'Successfully authorized from %{kind} account.' + failure: 'Could not authorize you from %{kind} because "%{reason}".' + mailer: + confirmation_instructions: + subject: 'Confirmation instructions' + reset_password_instructions: + subject: 'Reset password instructions' + unlock_instructions: + subject: 'Unlock Instructions' diff --git a/config/routes.rb b/config/routes.rb index a5db786..03378f0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,7 @@ Planet::Application.routes.draw do + devise_for :users + resources :sites get "types/ordered_index" diff --git a/db/migrate/20120415155937_devise_create_users.rb b/db/migrate/20120415155937_devise_create_users.rb new file mode 100644 index 0000000..540333c --- /dev/null +++ b/db/migrate/20120415155937_devise_create_users.rb @@ -0,0 +1,49 @@ +class DeviseCreateUsers < ActiveRecord::Migration + def change + create_table(:users) do |t| + ## Database authenticatable + t.string :email, :null => false, :default => "" + t.string :encrypted_password, :null => false, :default => "" + + ## Recoverable + t.string :reset_password_token + t.datetime :reset_password_sent_at + + ## Rememberable + t.datetime :remember_created_at + + ## Trackable + t.integer :sign_in_count, :default => 0 + t.datetime :current_sign_in_at + t.datetime :last_sign_in_at + t.string :current_sign_in_ip + t.string :last_sign_in_ip + + ## Encryptable + # t.string :password_salt + + ## Confirmable + # t.string :confirmation_token + # t.datetime :confirmed_at + # t.datetime :confirmation_sent_at + # t.string :unconfirmed_email # Only if using reconfirmable + + ## Lockable + # t.integer :failed_attempts, :default => 0 # Only if lock strategy is :failed_attempts + # t.string :unlock_token # Only if unlock strategy is :email or :both + # t.datetime :locked_at + + ## Token authenticatable + # t.string :authentication_token + + + t.timestamps + end + + add_index :users, :email, :unique => true + add_index :users, :reset_password_token, :unique => true + # add_index :users, :confirmation_token, :unique => true + # add_index :users, :unlock_token, :unique => true + # add_index :users, :authentication_token, :unique => true + end +end diff --git a/db/migrate/20120415160149_user_name.rb b/db/migrate/20120415160149_user_name.rb new file mode 100644 index 0000000..85b4110 --- /dev/null +++ b/db/migrate/20120415160149_user_name.rb @@ -0,0 +1,13 @@ +class UserName < ActiveRecord::Migration + def up + change_table :users do |t| + t.column :name, :string + end + end + + def down + change_table :users do |t| + t.remove :name + end + end +end diff --git a/db/schema.rb b/db/schema.rb index de057ba..ccfd858 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120320100145) do +ActiveRecord::Schema.define(:version => 20120415160149) do create_table "sites", :force => true do |t| t.string "name" @@ -29,4 +29,23 @@ t.datetime "updated_at", :null => false end + create_table "users", :force => true do |t| + t.string "email", :default => "", :null => false + t.string "encrypted_password", :default => "", :null => false + t.string "reset_password_token" + t.datetime "reset_password_sent_at" + t.datetime "remember_created_at" + t.integer "sign_in_count", :default => 0 + t.datetime "current_sign_in_at" + t.datetime "last_sign_in_at" + t.string "current_sign_in_ip" + t.string "last_sign_in_ip" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + t.string "name" + end + + add_index "users", ["email"], :name => "index_users_on_email", :unique => true + add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true + end diff --git a/test/fixtures/users.yml b/test/fixtures/users.yml new file mode 100644 index 0000000..c63aac0 --- /dev/null +++ b/test/fixtures/users.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html + +# This model initially had no columns defined. If you add columns to the +# model remove the '{}' from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/unit/user_test.rb b/test/unit/user_test.rb new file mode 100644 index 0000000..82f61e0 --- /dev/null +++ b/test/unit/user_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class UserTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end From 7c00712a1dfc8682c9c6fb0d36852abd0292335e Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Sun, 15 Apr 2012 18:05:33 +0200 Subject: [PATCH 04/14] generate devise:views --- app/views/devise/_links.erb | 25 +++++++++++++++++++ app/views/devise/confirmations/new.html.erb | 12 +++++++++ .../mailer/confirmation_instructions.html.erb | 5 ++++ .../reset_password_instructions.html.erb | 8 ++++++ .../mailer/unlock_instructions.html.erb | 7 ++++++ app/views/devise/passwords/edit.html.erb | 16 ++++++++++++ app/views/devise/passwords/new.html.erb | 12 +++++++++ app/views/devise/registrations/edit.html.erb | 25 +++++++++++++++++++ app/views/devise/registrations/new.html.erb | 18 +++++++++++++ app/views/devise/sessions/new.html.erb | 17 +++++++++++++ app/views/devise/unlocks/new.html.erb | 12 +++++++++ 11 files changed, 157 insertions(+) create mode 100644 app/views/devise/_links.erb create mode 100644 app/views/devise/confirmations/new.html.erb create mode 100644 app/views/devise/mailer/confirmation_instructions.html.erb create mode 100644 app/views/devise/mailer/reset_password_instructions.html.erb create mode 100644 app/views/devise/mailer/unlock_instructions.html.erb create mode 100644 app/views/devise/passwords/edit.html.erb create mode 100644 app/views/devise/passwords/new.html.erb create mode 100644 app/views/devise/registrations/edit.html.erb create mode 100644 app/views/devise/registrations/new.html.erb create mode 100644 app/views/devise/sessions/new.html.erb create mode 100644 app/views/devise/unlocks/new.html.erb diff --git a/app/views/devise/_links.erb b/app/views/devise/_links.erb new file mode 100644 index 0000000..eab783a --- /dev/null +++ b/app/views/devise/_links.erb @@ -0,0 +1,25 @@ +<%- if controller_name != 'sessions' %> + <%= link_to "Sign in", new_session_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.registerable? && controller_name != 'registrations' %> + <%= link_to "Sign up", new_registration_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.recoverable? && controller_name != 'passwords' %> + <%= link_to "Forgot your password?", new_password_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.confirmable? && controller_name != 'confirmations' %> + <%= link_to "Didn't receive confirmation instructions?", new_confirmation_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.lockable? && resource_class.unlock_strategy_enabled?(:email) && controller_name != 'unlocks' %> + <%= link_to "Didn't receive unlock instructions?", new_unlock_path(resource_name) %>
+<% end -%> + +<%- if devise_mapping.omniauthable? %> + <%- resource_class.omniauth_providers.each do |provider| %> + <%= link_to "Sign in with #{provider.to_s.titleize}", omniauth_authorize_path(resource_name, provider) %>
+ <% end -%> +<% end -%> \ No newline at end of file diff --git a/app/views/devise/confirmations/new.html.erb b/app/views/devise/confirmations/new.html.erb new file mode 100644 index 0000000..18d81b1 --- /dev/null +++ b/app/views/devise/confirmations/new.html.erb @@ -0,0 +1,12 @@ +

Resend confirmation instructions

+ +<%= form_for(resource, :as => resource_name, :url => confirmation_path(resource_name), :html => { :method => :post }) do |f| %> + <%= devise_error_messages! %> + +
<%= f.label :email %>
+ <%= f.email_field :email %>
+ +
<%= f.submit "Resend confirmation instructions" %>
+<% end %> + +<%= render "links" %> \ No newline at end of file diff --git a/app/views/devise/mailer/confirmation_instructions.html.erb b/app/views/devise/mailer/confirmation_instructions.html.erb new file mode 100644 index 0000000..a5c4585 --- /dev/null +++ b/app/views/devise/mailer/confirmation_instructions.html.erb @@ -0,0 +1,5 @@ +

Welcome <%= @resource.email %>!

+ +

You can confirm your account email through the link below:

+ +

<%= link_to 'Confirm my account', confirmation_url(@resource, :confirmation_token => @resource.confirmation_token) %>

diff --git a/app/views/devise/mailer/reset_password_instructions.html.erb b/app/views/devise/mailer/reset_password_instructions.html.erb new file mode 100644 index 0000000..ae9e888 --- /dev/null +++ b/app/views/devise/mailer/reset_password_instructions.html.erb @@ -0,0 +1,8 @@ +

Hello <%= @resource.email %>!

+ +

Someone has requested a link to change your password, and you can do this through the link below.

+ +

<%= link_to 'Change my password', edit_password_url(@resource, :reset_password_token => @resource.reset_password_token) %>

+ +

If you didn't request this, please ignore this email.

+

Your password won't change until you access the link above and create a new one.

diff --git a/app/views/devise/mailer/unlock_instructions.html.erb b/app/views/devise/mailer/unlock_instructions.html.erb new file mode 100644 index 0000000..2263c21 --- /dev/null +++ b/app/views/devise/mailer/unlock_instructions.html.erb @@ -0,0 +1,7 @@ +

Hello <%= @resource.email %>!

+ +

Your account has been locked due to an excessive amount of unsuccessful sign in attempts.

+ +

Click the link below to unlock your account:

+ +

<%= link_to 'Unlock my account', unlock_url(@resource, :unlock_token => @resource.unlock_token) %>

diff --git a/app/views/devise/passwords/edit.html.erb b/app/views/devise/passwords/edit.html.erb new file mode 100644 index 0000000..5f7bcf8 --- /dev/null +++ b/app/views/devise/passwords/edit.html.erb @@ -0,0 +1,16 @@ +

Change your password

+ +<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :put }) do |f| %> + <%= devise_error_messages! %> + <%= f.hidden_field :reset_password_token %> + +
<%= f.label :password, "New password" %>
+ <%= f.password_field :password %>
+ +
<%= f.label :password_confirmation, "Confirm new password" %>
+ <%= f.password_field :password_confirmation %>
+ +
<%= f.submit "Change my password" %>
+<% end %> + +<%= render "links" %> \ No newline at end of file diff --git a/app/views/devise/passwords/new.html.erb b/app/views/devise/passwords/new.html.erb new file mode 100644 index 0000000..b0b5690 --- /dev/null +++ b/app/views/devise/passwords/new.html.erb @@ -0,0 +1,12 @@ +

Forgot your password?

+ +<%= form_for(resource, :as => resource_name, :url => password_path(resource_name), :html => { :method => :post }) do |f| %> + <%= devise_error_messages! %> + +
<%= f.label :email %>
+ <%= f.email_field :email %>
+ +
<%= f.submit "Send me reset password instructions" %>
+<% end %> + +<%= render "links" %> \ No newline at end of file diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb new file mode 100644 index 0000000..bb66fbf --- /dev/null +++ b/app/views/devise/registrations/edit.html.erb @@ -0,0 +1,25 @@ +

Edit <%= resource_name.to_s.humanize %>

+ +<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %> + <%= devise_error_messages! %> + +
<%= f.label :email %>
+ <%= f.email_field :email %>
+ +
<%= f.label :password %> (leave blank if you don't want to change it)
+ <%= f.password_field :password, :autocomplete => "off" %>
+ +
<%= f.label :password_confirmation %>
+ <%= f.password_field :password_confirmation %>
+ +
<%= f.label :current_password %> (we need your current password to confirm your changes)
+ <%= f.password_field :current_password %>
+ +
<%= f.submit "Update" %>
+<% end %> + +

Cancel my account

+ +

Unhappy? <%= link_to "Cancel my account", registration_path(resource_name), :confirm => "Are you sure?", :method => :delete %>.

+ +<%= link_to "Back", :back %> diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb new file mode 100644 index 0000000..f5136f1 --- /dev/null +++ b/app/views/devise/registrations/new.html.erb @@ -0,0 +1,18 @@ +

Sign up

+ +<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %> + <%= devise_error_messages! %> + +
<%= f.label :email %>
+ <%= f.email_field :email %>
+ +
<%= f.label :password %>
+ <%= f.password_field :password %>
+ +
<%= f.label :password_confirmation %>
+ <%= f.password_field :password_confirmation %>
+ +
<%= f.submit "Sign up" %>
+<% end %> + +<%= render "links" %> diff --git a/app/views/devise/sessions/new.html.erb b/app/views/devise/sessions/new.html.erb new file mode 100644 index 0000000..f12116b --- /dev/null +++ b/app/views/devise/sessions/new.html.erb @@ -0,0 +1,17 @@ +

Sign in

+ +<%= form_for(resource, :as => resource_name, :url => session_path(resource_name)) do |f| %> +
<%= f.label :email %>
+ <%= f.email_field :email %>
+ +
<%= f.label :password %>
+ <%= f.password_field :password %>
+ + <% if devise_mapping.rememberable? -%> +
<%= f.check_box :remember_me %> <%= f.label :remember_me %>
+ <% end -%> + +
<%= f.submit "Sign in" %>
+<% end %> + +<%= render "links" %> \ No newline at end of file diff --git a/app/views/devise/unlocks/new.html.erb b/app/views/devise/unlocks/new.html.erb new file mode 100644 index 0000000..0dc79ac --- /dev/null +++ b/app/views/devise/unlocks/new.html.erb @@ -0,0 +1,12 @@ +

Resend unlock instructions

+ +<%= form_for(resource, :as => resource_name, :url => unlock_path(resource_name), :html => { :method => :post }) do |f| %> + <%= devise_error_messages! %> + +
<%= f.label :email %>
+ <%= f.email_field :email %>
+ +
<%= f.submit "Resend unlock instructions" %>
+<% end %> + +<%= render "links" %> \ No newline at end of file From 8e46bee631463d7540fa40eb69ca9fef715780e2 Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Sun, 15 Apr 2012 19:25:43 +0200 Subject: [PATCH 05/14] generate devise:views --- app/assets/stylesheets/planet.css | 13 +++++++++++++ app/views/devise/registrations/edit.html.erb | 3 +++ app/views/devise/registrations/new.html.erb | 3 +++ app/views/layouts/application.html.erb | 11 ++++++++++- 4 files changed, 29 insertions(+), 1 deletion(-) diff --git a/app/assets/stylesheets/planet.css b/app/assets/stylesheets/planet.css index 3ee40a6..b0555ed 100644 --- a/app/assets/stylesheets/planet.css +++ b/app/assets/stylesheets/planet.css @@ -104,6 +104,19 @@ word-spacing:25pt; padding-left: 10px; } +#banner .user { + margin-top: 50px; + margin-right:20px; + float: right; + color: #bfb; + font-size: small; + +} + +#banner .user a { + color:#555; +} + #columns { background: #446; } diff --git a/app/views/devise/registrations/edit.html.erb b/app/views/devise/registrations/edit.html.erb index bb66fbf..5d4a937 100644 --- a/app/views/devise/registrations/edit.html.erb +++ b/app/views/devise/registrations/edit.html.erb @@ -3,6 +3,9 @@ <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :put }) do |f| %> <%= devise_error_messages! %> +
<%= f.label :name %>
+<%= f.text_field :name %>
+
<%= f.label :email %>
<%= f.email_field :email %>
diff --git a/app/views/devise/registrations/new.html.erb b/app/views/devise/registrations/new.html.erb index f5136f1..06911fd 100644 --- a/app/views/devise/registrations/new.html.erb +++ b/app/views/devise/registrations/new.html.erb @@ -3,6 +3,9 @@ <%= form_for(resource, :as => resource_name, :url => registration_path(resource_name)) do |f| %> <%= devise_error_messages! %> +
<%= f.label :name %>
+ <%= f.text_field :name %>
+
<%= f.label :email %>
<%= f.email_field :email %>
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index ce6b6c1..4f3054d 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -29,6 +29,14 @@
@@ -36,7 +44,8 @@ <%= link_to "Home", planet_index_path %>
<%= link_to "Tipos", types_path %>
<%= link_to "Sitios", sites_path %>
- <%= link_to "Contact", planet_contact_path %> + <%= link_to "Contact", planet_contact_path %>
+ <%= link_to "Sign up", new_user_registration_path %>
From e58b4ab9e1f42f8975a8c80b50253105ea82f30d Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Sun, 15 Apr 2012 19:39:14 +0200 Subject: [PATCH 06/14] User Sites relation --- app/models/site.rb | 3 ++- app/models/user.rb | 1 + db/migrate/20120415172636_user_sites.rb | 13 +++++++++++++ db/schema.rb | 3 ++- 4 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 db/migrate/20120415172636_user_sites.rb diff --git a/app/models/site.rb b/app/models/site.rb index 31f4370..bb9b7d4 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -1,10 +1,11 @@ class Site < ActiveRecord::Base belongs_to :type + belongs_to :user # Debe estar protegido para evitar accesos indeseados - + attr_protected :user_id # Se añaden estas definiciones validates :name, :type_id,:image_url, :presence => true # campo obligatorio diff --git a/app/models/user.rb b/app/models/user.rb index d6c2cd3..172045c 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,4 +1,5 @@ class User < ActiveRecord::Base + has_many :sites # Include default devise modules. Others available are: # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, diff --git a/db/migrate/20120415172636_user_sites.rb b/db/migrate/20120415172636_user_sites.rb new file mode 100644 index 0000000..9c01834 --- /dev/null +++ b/db/migrate/20120415172636_user_sites.rb @@ -0,0 +1,13 @@ +class UserSites < ActiveRecord::Migration + def up + change_table :sites do |t| + t.column :user_id,:integer + end + end + + def down + change_table :sites do |t| + t.remove :user_id + end + end +end diff --git a/db/schema.rb b/db/schema.rb index ccfd858..20bf370 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120415160149) do +ActiveRecord::Schema.define(:version => 20120415172636) do create_table "sites", :force => true do |t| t.string "name" @@ -20,6 +20,7 @@ t.string "image_url" t.datetime "created_at", :null => false t.datetime "updated_at", :null => false + t.integer "user_id" end create_table "types", :force => true do |t| From 656f7a44c29a7261a5f69c33d0581c11f317c8f5 Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Sun, 15 Apr 2012 21:39:49 +0200 Subject: [PATCH 07/14] Entrega 6 --- app/assets/javascripts/comentarios.js.coffee | 3 + app/assets/stylesheets/comentarios.css.scss | 3 + app/controllers/comentarios_controller.rb | 93 +++++++++++++++++++ app/controllers/sites_controller.rb | 12 ++- app/helpers/comentarios_helper.rb | 2 + app/models/comentario.rb | 8 ++ app/models/site.rb | 1 + app/models/user.rb | 1 + app/views/comentarios/_form.html.erb | 29 ++++++ app/views/comentarios/edit.html.erb | 6 ++ app/views/comentarios/index.html.erb | 43 +++++++++ app/views/comentarios/new.html.erb | 5 + app/views/comentarios/show.html.erb | 20 ++++ app/views/sites/index.html.erb | 9 ++ app/views/sites/show.html.erb | 19 +++- config/routes.rb | 9 +- .../20120415175613_create_comentarios.rb | 11 +++ db/schema.rb | 10 +- test/fixtures/comentarios.yml | 11 +++ .../functional/comentarios_controller_test.rb | 49 ++++++++++ test/unit/comentario_test.rb | 7 ++ test/unit/helpers/comentarios_helper_test.rb | 4 + 22 files changed, 347 insertions(+), 8 deletions(-) create mode 100644 app/assets/javascripts/comentarios.js.coffee create mode 100644 app/assets/stylesheets/comentarios.css.scss create mode 100644 app/controllers/comentarios_controller.rb create mode 100644 app/helpers/comentarios_helper.rb create mode 100644 app/models/comentario.rb create mode 100644 app/views/comentarios/_form.html.erb create mode 100644 app/views/comentarios/edit.html.erb create mode 100644 app/views/comentarios/index.html.erb create mode 100644 app/views/comentarios/new.html.erb create mode 100644 app/views/comentarios/show.html.erb create mode 100644 db/migrate/20120415175613_create_comentarios.rb create mode 100644 test/fixtures/comentarios.yml create mode 100644 test/functional/comentarios_controller_test.rb create mode 100644 test/unit/comentario_test.rb create mode 100644 test/unit/helpers/comentarios_helper_test.rb diff --git a/app/assets/javascripts/comentarios.js.coffee b/app/assets/javascripts/comentarios.js.coffee new file mode 100644 index 0000000..7615679 --- /dev/null +++ b/app/assets/javascripts/comentarios.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/stylesheets/comentarios.css.scss b/app/assets/stylesheets/comentarios.css.scss new file mode 100644 index 0000000..494c101 --- /dev/null +++ b/app/assets/stylesheets/comentarios.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the comentarios controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/comentarios_controller.rb b/app/controllers/comentarios_controller.rb new file mode 100644 index 0000000..ded944b --- /dev/null +++ b/app/controllers/comentarios_controller.rb @@ -0,0 +1,93 @@ +class ComentariosController < ApplicationController + # GET /comentarios + # GET /comentarios.json + before_filter :authenticate_user!, :except => [:index,:show] + def index + if params[:site_id].nil? or params[:site_id].empty? + + if params[:user_id].nil? or params[:user_id].empty? + @comentarios = Comentario.all # path: /types + else + @comentarios = User.find(params[:user_id]).comentarios + end + + else + @comentarios = Site.find(params[:site_id]).comentarios # path: /types/id/sites + end + respond_to do |format| + format.html # index.html.erb + format.json { render json: @sites } + end + end + + # GET /comentarios/1 + # GET /comentarios/1.json + def show + @comentario = Comentario.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.json { render json: @comentario } + end + end + + # GET /comentarios/new + # GET /comentarios/new.json + def new + @comentario = current_user.comentarios.build + + respond_to do |format| + format.html # new.html.erb + format.json { render json: @comentario } + end + end + + # GET /comentarios/1/edit + def edit + @comentario = current_user.comentarios.find(params[:id]) + end + + # POST /comentarios + # POST /comentarios.json + def create + @comentario = current_user.comentarios.build(params[:comentario]) + + respond_to do |format| + if @comentario.save + format.html { redirect_to @comentario, notice: 'Comentario was successfully created.' } + format.json { render json: @comentario, status: :created, location: @comentario } + else + format.html { render action: "new" } + format.json { render json: @comentario.errors, status: :unprocessable_entity } + end + end + end + + # PUT /comentarios/1 + # PUT /comentarios/1.json + def update + @comentario = current_user.comentarios.build(params[:id]) + + respond_to do |format| + if @comentario.update_attributes(params[:comentario]) + format.html { redirect_to @comentario, notice: 'Comentario was successfully updated.' } + format.json { head :no_content } + else + format.html { render action: "edit" } + format.json { render json: @comentario.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /comentarios/1 + # DELETE /comentarios/1.json + def destroy + @comentario = current_user.comentarios.find(params[:id]) + @comentario.destroy + + respond_to do |format| + format.html { redirect_to comentarios_url } + format.json { head :no_content } + end + end +end diff --git a/app/controllers/sites_controller.rb b/app/controllers/sites_controller.rb index f3ae9ad..8daea0a 100644 --- a/app/controllers/sites_controller.rb +++ b/app/controllers/sites_controller.rb @@ -1,4 +1,6 @@ class SitesController < ApplicationController + + before_filter :authenticate_user!, :except => [:index,:show] # GET /sites # GET /sites.json def index @@ -27,7 +29,7 @@ def show # GET /sites/new # GET /sites/new.json def new - @site = Site.new + @site = current_user.sites.build #crea sitio vacio asociado a current user respond_to do |format| format.html # new.html.erb @@ -37,13 +39,13 @@ def new # GET /sites/1/edit def edit - @site = Site.find(params[:id]) + @site = current_user.sites.find(params[:id]) end # POST /sites # POST /sites.json def create - @site = Site.new(params[:site]) + @site = current_user.sites.build(params[:site]) respond_to do |format| if @site.save @@ -59,7 +61,7 @@ def create # PUT /sites/1 # PUT /sites/1.json def update - @site = Site.find(params[:id]) + @site = current_user.sites.find(params[:id]) respond_to do |format| if @site.update_attributes(params[:site]) @@ -75,7 +77,7 @@ def update # DELETE /sites/1 # DELETE /sites/1.json def destroy - @site = Site.find(params[:id]) + @site = current_user.sites.find(params[:id]) @site.destroy respond_to do |format| diff --git a/app/helpers/comentarios_helper.rb b/app/helpers/comentarios_helper.rb new file mode 100644 index 0000000..a8f928b --- /dev/null +++ b/app/helpers/comentarios_helper.rb @@ -0,0 +1,2 @@ +module ComentariosHelper +end diff --git a/app/models/comentario.rb b/app/models/comentario.rb new file mode 100644 index 0000000..fe49b14 --- /dev/null +++ b/app/models/comentario.rb @@ -0,0 +1,8 @@ +class Comentario < ActiveRecord::Base + belongs_to :site + belongs_to :user + + validates :site_id,:user_id, :presence => true #El comentario debe tener un contenido y pertenecer a un sitio y usuario + validates :coment, :presence => true, + :length => { :maximum => 240 } +end diff --git a/app/models/site.rb b/app/models/site.rb index bb9b7d4..f9b93cf 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -1,6 +1,7 @@ class Site < ActiveRecord::Base belongs_to :type belongs_to :user + has_many :comentarios diff --git a/app/models/user.rb b/app/models/user.rb index 172045c..74e9f24 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,5 +1,6 @@ class User < ActiveRecord::Base has_many :sites + has_many :comentarios # Include default devise modules. Others available are: # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, diff --git a/app/views/comentarios/_form.html.erb b/app/views/comentarios/_form.html.erb new file mode 100644 index 0000000..59a35a4 --- /dev/null +++ b/app/views/comentarios/_form.html.erb @@ -0,0 +1,29 @@ +<%= form_for(@comentario) do |f| %> + <% if @comentario.errors.any? %> +
+

<%= pluralize(@comentario.errors.count, "error") %> prohibited this comentario from being saved:

+ +
    + <% @comentario.errors.full_messages.each do |msg| %> +
  • <%= msg %>
  • + <% end %> +
+
+ <% end %> + +
+ <%= f.label :coment %>
+ <%= f.text_field :coment %> +
+
+ <%= f.label :user_id %>
+ <%= f.number_field :user_id %> +
+
+ <%= f.label :site_id %>
+ <%= f.number_field :site_id %> +
+
+ <%= f.submit %> +
+<% end %> diff --git a/app/views/comentarios/edit.html.erb b/app/views/comentarios/edit.html.erb new file mode 100644 index 0000000..9a8929b --- /dev/null +++ b/app/views/comentarios/edit.html.erb @@ -0,0 +1,6 @@ +

Editing comentario

+ +<%= render 'form' %> + +<%= link_to 'Show', @comentario %> | +<%= link_to 'Back', comentarios_path %> diff --git a/app/views/comentarios/index.html.erb b/app/views/comentarios/index.html.erb new file mode 100644 index 0000000..b1483ec --- /dev/null +++ b/app/views/comentarios/index.html.erb @@ -0,0 +1,43 @@ + +
+

Listing Comentarios

+ + + <% @comentarios.each do |comentario| %> + + + + + + + + + <% end %> +
+
+ +
<%= strip_tags(comentario.coment) + %>
+ +
+
+ <%= link_to 'Show', comentario %>
+ + + <% if comentario.user == current_user %> + <%= link_to 'Edit', edit_comentario_path(comentario) %>
+ <%= link_to 'Destroy', comentario, + :confirm => 'Are you sure?', + :method => :delete %> + <% end %> +
+
+ +
+ +<%= link_to 'Añadir Comentario', new_comentario_path %> + + + + + diff --git a/app/views/comentarios/new.html.erb b/app/views/comentarios/new.html.erb new file mode 100644 index 0000000..5310e0c --- /dev/null +++ b/app/views/comentarios/new.html.erb @@ -0,0 +1,5 @@ +

New comentario

+ +<%= render 'form' %> + +<%= link_to 'Back', comentarios_path %> diff --git a/app/views/comentarios/show.html.erb b/app/views/comentarios/show.html.erb new file mode 100644 index 0000000..bed947d --- /dev/null +++ b/app/views/comentarios/show.html.erb @@ -0,0 +1,20 @@ +

<%= notice %>

+ +

+ Coment: + <%= @comentario.coment %> +

+ +

+ User: + <%= @comentario.user_id %> +

+ +

+ Site: + <%= @comentario.site_id %> +

+ + +<%= link_to 'Edit', edit_comentario_path(@comentario) %> | +<%= link_to 'Back', comentarios_path %> diff --git a/app/views/sites/index.html.erb b/app/views/sites/index.html.erb index f1034b8..2d42d09 100644 --- a/app/views/sites/index.html.erb +++ b/app/views/sites/index.html.erb @@ -14,15 +14,24 @@
<%= link_to site.name, site %>
<%= truncate(strip_tags(site.description), :length => 80) %>
+ <%= link_to 'Show', site %>
+ <% if not(site.comentarios.empty?) %> + + <%= link_to 'Comentarios', site_comentarios_path(site) %> + + <% end %> + + <% if site.user == current_user %> <%= link_to 'Edit', edit_site_path(site) %>
<%= link_to 'Destroy', site, :confirm => 'Are you sure?', :method => :delete %> + <% end %> <% end %> diff --git a/app/views/sites/show.html.erb b/app/views/sites/show.html.erb index 94dc17a..b01aa02 100644 --- a/app/views/sites/show.html.erb +++ b/app/views/sites/show.html.erb @@ -7,9 +7,26 @@

<%= @site.name %>

<%=sanitize @site.description %>

- +

Autor: + <%= @site.user.name if @site.user %>

+<% if @site.user == current_user %> <%= link_to 'Edit', edit_site_path(@site) %> | +<% end %> <%= link_to 'Back', sites_path %> + +<% if not(@site.comentarios.empty?) %> +<% @site.comentarios.each do |comentario| %> + +

+ +
<%= comentario.user.name if comentario.user %> : <%= strip_tags(comentario.coment) + %>
+ +
+ +<% end %> +<% end %> +<%= link_to 'Añada Comentario', new_comentario_path %> diff --git a/config/routes.rb b/config/routes.rb index 03378f0..6951b0b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,15 @@ Planet::Application.routes.draw do + resources :comentarios + + devise_for :users - resources :sites + resources :sites do + resources :comentarios, :only => [ :index ] + end + + get "types/ordered_index" diff --git a/db/migrate/20120415175613_create_comentarios.rb b/db/migrate/20120415175613_create_comentarios.rb new file mode 100644 index 0000000..1f46d24 --- /dev/null +++ b/db/migrate/20120415175613_create_comentarios.rb @@ -0,0 +1,11 @@ +class CreateComentarios < ActiveRecord::Migration + def change + create_table :comentarios do |t| + t.string :coment + t.integer :user_id + t.integer :site_id + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 20bf370..640ccf8 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,15 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120415172636) do +ActiveRecord::Schema.define(:version => 20120415175613) do + + create_table "comentarios", :force => true do |t| + t.string "coment" + t.integer "user_id" + t.integer "site_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end create_table "sites", :force => true do |t| t.string "name" diff --git a/test/fixtures/comentarios.yml b/test/fixtures/comentarios.yml new file mode 100644 index 0000000..e7e2ac9 --- /dev/null +++ b/test/fixtures/comentarios.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html + +one: + coment: MyString + user_id: 1 + site_id: 1 + +two: + coment: MyString + user_id: 1 + site_id: 1 diff --git a/test/functional/comentarios_controller_test.rb b/test/functional/comentarios_controller_test.rb new file mode 100644 index 0000000..2c09333 --- /dev/null +++ b/test/functional/comentarios_controller_test.rb @@ -0,0 +1,49 @@ +require 'test_helper' + +class ComentariosControllerTest < ActionController::TestCase + setup do + @comentario = comentarios(:one) + end + + test "should get index" do + get :index + assert_response :success + assert_not_nil assigns(:comentarios) + end + + test "should get new" do + get :new + assert_response :success + end + + test "should create comentario" do + assert_difference('Comentario.count') do + post :create, comentario: @comentario.attributes + end + + assert_redirected_to comentario_path(assigns(:comentario)) + end + + test "should show comentario" do + get :show, id: @comentario + assert_response :success + end + + test "should get edit" do + get :edit, id: @comentario + assert_response :success + end + + test "should update comentario" do + put :update, id: @comentario, comentario: @comentario.attributes + assert_redirected_to comentario_path(assigns(:comentario)) + end + + test "should destroy comentario" do + assert_difference('Comentario.count', -1) do + delete :destroy, id: @comentario + end + + assert_redirected_to comentarios_path + end +end diff --git a/test/unit/comentario_test.rb b/test/unit/comentario_test.rb new file mode 100644 index 0000000..02f982d --- /dev/null +++ b/test/unit/comentario_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class ComentarioTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end diff --git a/test/unit/helpers/comentarios_helper_test.rb b/test/unit/helpers/comentarios_helper_test.rb new file mode 100644 index 0000000..d553eef --- /dev/null +++ b/test/unit/helpers/comentarios_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class ComentariosHelperTest < ActionView::TestCase +end From c817b6da2bc0d6886e9441af5e852469556d655f Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Tue, 17 Apr 2012 12:30:30 +0200 Subject: [PATCH 08/14] scaffold trip --- app/assets/javascripts/trips.js.coffee | 3 + app/assets/stylesheets/trips.css.scss | 3 + app/controllers/comentarios_controller.rb | 38 ++++++----- app/controllers/trips_controller.rb | 83 +++++++++++++++++++++++ app/helpers/trips_helper.rb | 2 + app/models/trip.rb | 2 + app/views/comentarios/_form.html.erb | 20 +++--- app/views/comentarios/edit.html.erb | 8 ++- app/views/comentarios/index.html.erb | 23 ++++--- app/views/comentarios/new.html.erb | 2 +- app/views/sites/show.html.erb | 27 +++++--- app/views/trips/_form.html.erb | 33 +++++++++ app/views/trips/edit.html.erb | 6 ++ app/views/trips/index.html.erb | 29 ++++++++ app/views/trips/new.html.erb | 5 ++ app/views/trips/show.html.erb | 25 +++++++ config/routes.rb | 25 +++++-- db/migrate/20120417103003_create_trips.rb | 12 ++++ test/fixtures/trips.yml | 13 ++++ test/functional/trips_controller_test.rb | 49 +++++++++++++ test/unit/helpers/trips_helper_test.rb | 4 ++ test/unit/trip_test.rb | 7 ++ 22 files changed, 364 insertions(+), 55 deletions(-) create mode 100644 app/assets/javascripts/trips.js.coffee create mode 100644 app/assets/stylesheets/trips.css.scss create mode 100644 app/controllers/trips_controller.rb create mode 100644 app/helpers/trips_helper.rb create mode 100644 app/models/trip.rb create mode 100644 app/views/trips/_form.html.erb create mode 100644 app/views/trips/edit.html.erb create mode 100644 app/views/trips/index.html.erb create mode 100644 app/views/trips/new.html.erb create mode 100644 app/views/trips/show.html.erb create mode 100644 db/migrate/20120417103003_create_trips.rb create mode 100644 test/fixtures/trips.yml create mode 100644 test/functional/trips_controller_test.rb create mode 100644 test/unit/helpers/trips_helper_test.rb create mode 100644 test/unit/trip_test.rb diff --git a/app/assets/javascripts/trips.js.coffee b/app/assets/javascripts/trips.js.coffee new file mode 100644 index 0000000..7615679 --- /dev/null +++ b/app/assets/javascripts/trips.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/stylesheets/trips.css.scss b/app/assets/stylesheets/trips.css.scss new file mode 100644 index 0000000..473cbc3 --- /dev/null +++ b/app/assets/stylesheets/trips.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the trips controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/comentarios_controller.rb b/app/controllers/comentarios_controller.rb index ded944b..f499da7 100644 --- a/app/controllers/comentarios_controller.rb +++ b/app/controllers/comentarios_controller.rb @@ -3,20 +3,19 @@ class ComentariosController < ApplicationController # GET /comentarios.json before_filter :authenticate_user!, :except => [:index,:show] def index - if params[:site_id].nil? or params[:site_id].empty? + + - if params[:user_id].nil? or params[:user_id].empty? - @comentarios = Comentario.all # path: /types - else - @comentarios = User.find(params[:user_id]).comentarios - end - else @comentarios = Site.find(params[:site_id]).comentarios # path: /types/id/sites - end + @comentario = current_user.comentarios.build + + + respond_to do |format| format.html # index.html.erb format.json { render json: @sites } + end end @@ -34,7 +33,10 @@ def show # GET /comentarios/new # GET /comentarios/new.json def new + @comentario = current_user.comentarios.build + + respond_to do |format| format.html # new.html.erb @@ -45,17 +47,20 @@ def new # GET /comentarios/1/edit def edit @comentario = current_user.comentarios.find(params[:id]) + end # POST /comentarios # POST /comentarios.json def create - @comentario = current_user.comentarios.build(params[:comentario]) + + @comentario = current_user.comentarios.build(params[:comentario])#creamos un comentario con lo que nos pasa el formulario + @comentario.site_id = params[:site_id] respond_to do |format| if @comentario.save - format.html { redirect_to @comentario, notice: 'Comentario was successfully created.' } - format.json { render json: @comentario, status: :created, location: @comentario } + format.html { redirect_to site_comentarios_url, notice: 'Comentario was successfully created.' } + format.json { render json: site_comentarios_url, status: :created, location: site_comentarios_url } else format.html { render action: "new" } format.json { render json: @comentario.errors, status: :unprocessable_entity } @@ -66,11 +71,12 @@ def create # PUT /comentarios/1 # PUT /comentarios/1.json def update - @comentario = current_user.comentarios.build(params[:id]) - + @comentario = current_user.comentarios.find(params[:id]) #cogemos el comentario a actualizar + + respond_to do |format| - if @comentario.update_attributes(params[:comentario]) - format.html { redirect_to @comentario, notice: 'Comentario was successfully updated.' } + if @comentario.update_attributes(params[:comentario])#intentamos actualizar el comentario con el pasado por el formulario + format.html { redirect_to site_comentarios_path(@comentario.site) , notice: 'Comentario was successfully updated.' } format.json { head :no_content } else format.html { render action: "edit" } @@ -86,7 +92,7 @@ def destroy @comentario.destroy respond_to do |format| - format.html { redirect_to comentarios_url } + format.html { redirect_to site_comentarios_path(@comentario.site) } format.json { head :no_content } end end diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb new file mode 100644 index 0000000..c776169 --- /dev/null +++ b/app/controllers/trips_controller.rb @@ -0,0 +1,83 @@ +class TripsController < ApplicationController + # GET /trips + # GET /trips.json + def index + @trips = Trip.all + + respond_to do |format| + format.html # index.html.erb + format.json { render json: @trips } + end + end + + # GET /trips/1 + # GET /trips/1.json + def show + @trip = Trip.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.json { render json: @trip } + end + end + + # GET /trips/new + # GET /trips/new.json + def new + @trip = Trip.new + + respond_to do |format| + format.html # new.html.erb + format.json { render json: @trip } + end + end + + # GET /trips/1/edit + def edit + @trip = Trip.find(params[:id]) + end + + # POST /trips + # POST /trips.json + def create + @trip = Trip.new(params[:trip]) + + respond_to do |format| + if @trip.save + format.html { redirect_to @trip, notice: 'Trip was successfully created.' } + format.json { render json: @trip, status: :created, location: @trip } + else + format.html { render action: "new" } + format.json { render json: @trip.errors, status: :unprocessable_entity } + end + end + end + + # PUT /trips/1 + # PUT /trips/1.json + def update + @trip = Trip.find(params[:id]) + + respond_to do |format| + if @trip.update_attributes(params[:trip]) + format.html { redirect_to @trip, notice: 'Trip was successfully updated.' } + format.json { head :no_content } + else + format.html { render action: "edit" } + format.json { render json: @trip.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /trips/1 + # DELETE /trips/1.json + def destroy + @trip = Trip.find(params[:id]) + @trip.destroy + + respond_to do |format| + format.html { redirect_to trips_url } + format.json { head :no_content } + end + end +end diff --git a/app/helpers/trips_helper.rb b/app/helpers/trips_helper.rb new file mode 100644 index 0000000..04f333d --- /dev/null +++ b/app/helpers/trips_helper.rb @@ -0,0 +1,2 @@ +module TripsHelper +end diff --git a/app/models/trip.rb b/app/models/trip.rb new file mode 100644 index 0000000..d079af4 --- /dev/null +++ b/app/models/trip.rb @@ -0,0 +1,2 @@ +class Trip < ActiveRecord::Base +end diff --git a/app/views/comentarios/_form.html.erb b/app/views/comentarios/_form.html.erb index 59a35a4..d4c98a1 100644 --- a/app/views/comentarios/_form.html.erb +++ b/app/views/comentarios/_form.html.erb @@ -1,4 +1,4 @@ -<%= form_for(@comentario) do |f| %> +<%= form_for([:site, @comentario]) do |f| %> <% if @comentario.errors.any? %>

<%= pluralize(@comentario.errors.count, "error") %> prohibited this comentario from being saved:

@@ -11,19 +11,17 @@
<% end %> +

Introduzca Texto del Comentario:

+ + +
- <%= f.label :coment %>
- <%= f.text_field :coment %> -
-
- <%= f.label :user_id %>
- <%= f.number_field :user_id %> -
-
- <%= f.label :site_id %>
- <%= f.number_field :site_id %> + + <%= f.text_area :coment %>
+
<%= f.submit %>
+ <% end %> diff --git a/app/views/comentarios/edit.html.erb b/app/views/comentarios/edit.html.erb index 9a8929b..04d725d 100644 --- a/app/views/comentarios/edit.html.erb +++ b/app/views/comentarios/edit.html.erb @@ -1,6 +1,10 @@

Editing comentario

+Comentario Actual:
+ +<%= strip_tags(@comentario.coment) %> + <%= render 'form' %> -<%= link_to 'Show', @comentario %> | -<%= link_to 'Back', comentarios_path %> + + diff --git a/app/views/comentarios/index.html.erb b/app/views/comentarios/index.html.erb index b1483ec..2f9a38e 100644 --- a/app/views/comentarios/index.html.erb +++ b/app/views/comentarios/index.html.erb @@ -11,21 +11,28 @@
-
<%= strip_tags(comentario.coment) +
<%= comentario.user.name if comentario.user %> : <%= strip_tags(comentario.coment) %>
- <%= link_to 'Show', comentario %>
+ <% if comentario.user == current_user %> - <%= link_to 'Edit', edit_comentario_path(comentario) %>
- <%= link_to 'Destroy', comentario, - :confirm => 'Are you sure?', - :method => :delete %> +

+ <%= link_to 'Eliminar', [comentario.site, comentario], + :confirm => 'Are you sure?', + :method => :delete %> + + <%= link_to 'Editar', edit_site_comentario_path(comentario.site,comentario) %> + + + +

+ <% end %> @@ -34,8 +41,8 @@
- -<%= link_to 'Añadir Comentario', new_comentario_path %> + + diff --git a/app/views/comentarios/new.html.erb b/app/views/comentarios/new.html.erb index 5310e0c..fc76740 100644 --- a/app/views/comentarios/new.html.erb +++ b/app/views/comentarios/new.html.erb @@ -2,4 +2,4 @@ <%= render 'form' %> -<%= link_to 'Back', comentarios_path %> + diff --git a/app/views/sites/show.html.erb b/app/views/sites/show.html.erb index b01aa02..e6607e4 100644 --- a/app/views/sites/show.html.erb +++ b/app/views/sites/show.html.erb @@ -17,16 +17,23 @@ <% end %> <%= link_to 'Back', sites_path %> + <% if not(@site.comentarios.empty?) %> -<% @site.comentarios.each do |comentario| %> - -
- -
<%= comentario.user.name if comentario.user %> : <%= strip_tags(comentario.coment) - %>
- -
- + +<%= link_to 'Comentarios', site_comentarios_path(@site) %> + <% end %> +
+

Añadir Un Comentario:

+<%= form_for([@site, @site.comentarios.build]) do |f| %> + +
+ <%= f.label :coment %>
+ <%= f.text_area :coment %> +
+
+ <%= f.submit %> +
<% end %> -<%= link_to 'Añada Comentario', new_comentario_path %> + + diff --git a/app/views/trips/_form.html.erb b/app/views/trips/_form.html.erb new file mode 100644 index 0000000..85e8284 --- /dev/null +++ b/app/views/trips/_form.html.erb @@ -0,0 +1,33 @@ +<%= form_for(@trip) do |f| %> + <% if @trip.errors.any? %> +
+

<%= pluralize(@trip.errors.count, "error") %> prohibited this trip from being saved:

+ +
    + <% @trip.errors.full_messages.each do |msg| %> +
  • <%= msg %>
  • + <% end %> +
+
+ <% end %> + +
+ <%= f.label :name %>
+ <%= f.text_field :name %> +
+
+ <%= f.label :description %>
+ <%= f.text_field :description %> +
+
+ <%= f.label :date %>
+ <%= f.date_select :date %> +
+
+ <%= f.label :user_id %>
+ <%= f.number_field :user_id %> +
+
+ <%= f.submit %> +
+<% end %> diff --git a/app/views/trips/edit.html.erb b/app/views/trips/edit.html.erb new file mode 100644 index 0000000..71287a4 --- /dev/null +++ b/app/views/trips/edit.html.erb @@ -0,0 +1,6 @@ +

Editing trip

+ +<%= render 'form' %> + +<%= link_to 'Show', @trip %> | +<%= link_to 'Back', trips_path %> diff --git a/app/views/trips/index.html.erb b/app/views/trips/index.html.erb new file mode 100644 index 0000000..47f649b --- /dev/null +++ b/app/views/trips/index.html.erb @@ -0,0 +1,29 @@ +

Listing trips

+ + + + + + + + + + + + +<% @trips.each do |trip| %> + + + + + + + + + +<% end %> +
NameDescriptionDateUser
<%= trip.name %><%= trip.description %><%= trip.date %><%= trip.user_id %><%= link_to 'Show', trip %><%= link_to 'Edit', edit_trip_path(trip) %><%= link_to 'Destroy', trip, confirm: 'Are you sure?', method: :delete %>
+ +
+ +<%= link_to 'New Trip', new_trip_path %> diff --git a/app/views/trips/new.html.erb b/app/views/trips/new.html.erb new file mode 100644 index 0000000..dd3e49d --- /dev/null +++ b/app/views/trips/new.html.erb @@ -0,0 +1,5 @@ +

New trip

+ +<%= render 'form' %> + +<%= link_to 'Back', trips_path %> diff --git a/app/views/trips/show.html.erb b/app/views/trips/show.html.erb new file mode 100644 index 0000000..f764047 --- /dev/null +++ b/app/views/trips/show.html.erb @@ -0,0 +1,25 @@ +

<%= notice %>

+ +

+ Name: + <%= @trip.name %> +

+ +

+ Description: + <%= @trip.description %> +

+ +

+ Date: + <%= @trip.date %> +

+ +

+ User: + <%= @trip.user_id %> +

+ + +<%= link_to 'Edit', edit_trip_path(@trip) %> | +<%= link_to 'Back', trips_path %> diff --git a/config/routes.rb b/config/routes.rb index 6951b0b..480032b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,22 +1,33 @@ Planet::Application.routes.draw do - resources :comentarios + + + resources :trips devise_for :users - resources :sites do - resources :comentarios, :only => [ :index ] - end - + get "types/ordered_index" + - get "types/ordered_index" - resources :types do # Rutas anidadas /types/id/sites..., +resources :types do # Rutas anidadas /types/id/sites..., resources :sites, :only => [ :index ] # Restringe a acción “index” end + + + resources :sites do + resources :comentarios + + end + + + + + + get "planet/index" get "planet/contact" diff --git a/db/migrate/20120417103003_create_trips.rb b/db/migrate/20120417103003_create_trips.rb new file mode 100644 index 0000000..38d8303 --- /dev/null +++ b/db/migrate/20120417103003_create_trips.rb @@ -0,0 +1,12 @@ +class CreateTrips < ActiveRecord::Migration + def change + create_table :trips do |t| + t.string :name + t.tex :description + t.date :date + t.integer :user_id + + t.timestamps + end + end +end diff --git a/test/fixtures/trips.yml b/test/fixtures/trips.yml new file mode 100644 index 0000000..aeeced8 --- /dev/null +++ b/test/fixtures/trips.yml @@ -0,0 +1,13 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html + +one: + name: MyString + description: + date: 2012-04-17 + user_id: 1 + +two: + name: MyString + description: + date: 2012-04-17 + user_id: 1 diff --git a/test/functional/trips_controller_test.rb b/test/functional/trips_controller_test.rb new file mode 100644 index 0000000..b09dce2 --- /dev/null +++ b/test/functional/trips_controller_test.rb @@ -0,0 +1,49 @@ +require 'test_helper' + +class TripsControllerTest < ActionController::TestCase + setup do + @trip = trips(:one) + end + + test "should get index" do + get :index + assert_response :success + assert_not_nil assigns(:trips) + end + + test "should get new" do + get :new + assert_response :success + end + + test "should create trip" do + assert_difference('Trip.count') do + post :create, trip: @trip.attributes + end + + assert_redirected_to trip_path(assigns(:trip)) + end + + test "should show trip" do + get :show, id: @trip + assert_response :success + end + + test "should get edit" do + get :edit, id: @trip + assert_response :success + end + + test "should update trip" do + put :update, id: @trip, trip: @trip.attributes + assert_redirected_to trip_path(assigns(:trip)) + end + + test "should destroy trip" do + assert_difference('Trip.count', -1) do + delete :destroy, id: @trip + end + + assert_redirected_to trips_path + end +end diff --git a/test/unit/helpers/trips_helper_test.rb b/test/unit/helpers/trips_helper_test.rb new file mode 100644 index 0000000..dcfddff --- /dev/null +++ b/test/unit/helpers/trips_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class TripsHelperTest < ActionView::TestCase +end diff --git a/test/unit/trip_test.rb b/test/unit/trip_test.rb new file mode 100644 index 0000000..1ed8ca6 --- /dev/null +++ b/test/unit/trip_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class TripTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end From 144c720824301bf5fa5082d5ee3762ad41b37955 Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Tue, 17 Apr 2012 12:34:14 +0200 Subject: [PATCH 09/14] migracion trip --- db/migrate/20120417103003_create_trips.rb | 2 +- db/schema.rb | 11 ++++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/db/migrate/20120417103003_create_trips.rb b/db/migrate/20120417103003_create_trips.rb index 38d8303..9acf33c 100644 --- a/db/migrate/20120417103003_create_trips.rb +++ b/db/migrate/20120417103003_create_trips.rb @@ -2,7 +2,7 @@ class CreateTrips < ActiveRecord::Migration def change create_table :trips do |t| t.string :name - t.tex :description + t.text :description t.date :date t.integer :user_id diff --git a/db/schema.rb b/db/schema.rb index 640ccf8..eaf86e6 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120415175613) do +ActiveRecord::Schema.define(:version => 20120417103003) do create_table "comentarios", :force => true do |t| t.string "coment" @@ -31,6 +31,15 @@ t.integer "user_id" end + create_table "trips", :force => true do |t| + t.string "name" + t.text "description" + t.date "date" + t.integer "user_id" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + create_table "types", :force => true do |t| t.string "name" t.text "description" From 61909b4a3db6dd45ddba4951847d58c69b7dc0c6 Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Tue, 17 Apr 2012 13:01:08 +0200 Subject: [PATCH 10/14] mejorar vistas e incluir cleditor --- Gemfile | 3 ++ Gemfile.lock | 2 + app/assets/javascripts/application.js | 1 + app/assets/stylesheets/application.css | 1 + app/controllers/trips_controller.rb | 12 +++--- app/models/trip.rb | 3 ++ app/models/user.rb | 1 + app/views/layouts/application.html.erb | 1 + app/views/trips/_form.html.erb | 7 +--- app/views/trips/index.html.erb | 54 ++++++++++++++------------ app/views/trips/show.html.erb | 9 +++-- 11 files changed, 55 insertions(+), 39 deletions(-) diff --git a/Gemfile b/Gemfile index 7231379..262615e 100644 --- a/Gemfile +++ b/Gemfile @@ -9,6 +9,9 @@ gem 'sqlite3' gem 'devise' +gem 'jquery-rails' + +gem 'cleditor_rails' # Gems used only for assets and not required # in production environments by default. diff --git a/Gemfile.lock b/Gemfile.lock index b16d2d9..36f623e 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -31,6 +31,7 @@ GEM arel (3.0.2) bcrypt-ruby (3.0.1) builder (3.0.0) + cleditor_rails (0.0.3) coffee-rails (3.2.2) coffee-script (>= 2.2.0) railties (~> 3.2.0) @@ -112,6 +113,7 @@ PLATFORMS ruby DEPENDENCIES + cleditor_rails coffee-rails (~> 3.2.1) devise jquery-rails diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js index 9097d83..84d87a2 100644 --- a/app/assets/javascripts/application.js +++ b/app/assets/javascripts/application.js @@ -11,5 +11,6 @@ // GO AFTER THE REQUIRES BELOW. // //= require jquery +//= require cleditor //= require jquery_ujs //= require_tree . diff --git a/app/assets/stylesheets/application.css b/app/assets/stylesheets/application.css index 3b5cc66..50d53e3 100644 --- a/app/assets/stylesheets/application.css +++ b/app/assets/stylesheets/application.css @@ -9,5 +9,6 @@ * compiled file, but it's generally better to create a new file per style scope. * *= require_self + *= require cleditor *= require_tree . */ diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index c776169..3764486 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -1,4 +1,6 @@ class TripsController < ApplicationController + + before_filter :authenticate_user!, :except => [:index, :show] # GET /trips # GET /trips.json def index @@ -24,7 +26,7 @@ def show # GET /trips/new # GET /trips/new.json def new - @trip = Trip.new + @trip = current_user.trips.build #crea viaje vacio respond_to do |format| format.html # new.html.erb @@ -34,13 +36,13 @@ def new # GET /trips/1/edit def edit - @trip = Trip.find(params[:id]) + @trip = current_user.trips.find(params[:id]) end # POST /trips # POST /trips.json def create - @trip = Trip.new(params[:trip]) + @trip = current_user.trips.build(params[:trip]) respond_to do |format| if @trip.save @@ -56,7 +58,7 @@ def create # PUT /trips/1 # PUT /trips/1.json def update - @trip = Trip.find(params[:id]) + @trip = current_user.trips.find(params[:id]) respond_to do |format| if @trip.update_attributes(params[:trip]) @@ -72,7 +74,7 @@ def update # DELETE /trips/1 # DELETE /trips/1.json def destroy - @trip = Trip.find(params[:id]) + @trip = current_user.trips.find(params[:id]) @trip.destroy respond_to do |format| diff --git a/app/models/trip.rb b/app/models/trip.rb index d079af4..6f517ed 100644 --- a/app/models/trip.rb +++ b/app/models/trip.rb @@ -1,2 +1,5 @@ class Trip < ActiveRecord::Base + belongs_to :user + + attr_protected :user_id #Por Seguridad end diff --git a/app/models/user.rb b/app/models/user.rb index 74e9f24..f4fa6f7 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -1,6 +1,7 @@ class User < ActiveRecord::Base has_many :sites has_many :comentarios + has_many :trips # Include default devise modules. Others available are: # :token_authenticatable, :encryptable, :confirmable, :lockable, :timeoutable and :omniauthable devise :database_authenticatable, :registerable, diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 4f3054d..4ee8275 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -44,6 +44,7 @@ <%= link_to "Home", planet_index_path %>
<%= link_to "Tipos", types_path %>
<%= link_to "Sitios", sites_path %>
+ <% link_to "Viajes", trips_path %>
<%= link_to "Contact", planet_contact_path %>
<%= link_to "Sign up", new_user_registration_path %> diff --git a/app/views/trips/_form.html.erb b/app/views/trips/_form.html.erb index 85e8284..94c5a4e 100644 --- a/app/views/trips/_form.html.erb +++ b/app/views/trips/_form.html.erb @@ -17,16 +17,13 @@
<%= f.label :description %>
- <%= f.text_field :description %> + <%= f.text_area :description %>
<%= f.label :date %>
<%= f.date_select :date %>
-
- <%= f.label :user_id %>
- <%= f.number_field :user_id %> -
+
<%= f.submit %>
diff --git a/app/views/trips/index.html.erb b/app/views/trips/index.html.erb index 47f649b..77fb9c5 100644 --- a/app/views/trips/index.html.erb +++ b/app/views/trips/index.html.erb @@ -1,28 +1,32 @@ -

Listing trips

- - - - - - - - - - - - -<% @trips.each do |trip| %> - - - - - - - - - -<% end %> -
NameDescriptionDateUser
<%= trip.name %><%= trip.description %><%= trip.date %><%= trip.user_id %><%= link_to 'Show', trip %><%= link_to 'Edit', edit_trip_path(trip) %><%= link_to 'Destroy', trip, confirm: 'Are you sure?', method: :delete %>
+
+

Viajes

+ + + <% @trips.each do |trip| %> + + + + + + + <% end %> +
+
+
<%= link_to trip.name, trip_path(trip) %>
+
<%= truncate(strip_tags(trip.description), + :length => 80) + ', ' + trip.date.to_s %>
+
Fecha última actualización : <%= trip.updated_at %>
+
+
+ <%= link_to 'Show', trip %>
+ <% if trip.user == current_user %> + <%= link_to 'Edit', edit_trip_path(type) %>
+ <%= link_to 'Destroy', trip, + :confirm => 'Are you sure?', + :method => :delete %> + <% end %> +
+

diff --git a/app/views/trips/show.html.erb b/app/views/trips/show.html.erb index f764047..d3b44da 100644 --- a/app/views/trips/show.html.erb +++ b/app/views/trips/show.html.erb @@ -7,7 +7,7 @@

Description: - <%= @trip.description %> + <%= simple_format @trip.description %>

@@ -16,10 +16,11 @@

- User: - <%= @trip.user_id %> + Autor: + <%= @trip.user.name if @trip.user %>

- +<% if @trip.user == current_user %> <%= link_to 'Edit', edit_trip_path(@trip) %> | +<% end %> <%= link_to 'Back', trips_path %> From e05d79e0dfca6d60748c6e92453af0b6d9e92b28 Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Tue, 17 Apr 2012 16:30:48 +0200 Subject: [PATCH 11/14] scaffold y migracion visit --- app/assets/javascripts/visits.js.coffee | 3 + app/assets/stylesheets/visits.css.scss | 3 + app/controllers/visits_controller.rb | 83 ++++++++++++++++++++++ app/helpers/visits_helper.rb | 2 + app/models/visit.rb | 2 + app/views/layouts/application.html.erb | 2 +- app/views/trips/index.html.erb | 2 +- app/views/visits/_form.html.erb | 29 ++++++++ app/views/visits/edit.html.erb | 6 ++ app/views/visits/index.html.erb | 27 +++++++ app/views/visits/new.html.erb | 5 ++ app/views/visits/show.html.erb | 20 ++++++ config/routes.rb | 2 + db/migrate/20120417143006_create_visits.rb | 11 +++ db/schema.rb | 10 ++- test/fixtures/visits.yml | 11 +++ test/functional/visits_controller_test.rb | 49 +++++++++++++ test/unit/helpers/visits_helper_test.rb | 4 ++ test/unit/visit_test.rb | 7 ++ 19 files changed, 275 insertions(+), 3 deletions(-) create mode 100644 app/assets/javascripts/visits.js.coffee create mode 100644 app/assets/stylesheets/visits.css.scss create mode 100644 app/controllers/visits_controller.rb create mode 100644 app/helpers/visits_helper.rb create mode 100644 app/models/visit.rb create mode 100644 app/views/visits/_form.html.erb create mode 100644 app/views/visits/edit.html.erb create mode 100644 app/views/visits/index.html.erb create mode 100644 app/views/visits/new.html.erb create mode 100644 app/views/visits/show.html.erb create mode 100644 db/migrate/20120417143006_create_visits.rb create mode 100644 test/fixtures/visits.yml create mode 100644 test/functional/visits_controller_test.rb create mode 100644 test/unit/helpers/visits_helper_test.rb create mode 100644 test/unit/visit_test.rb diff --git a/app/assets/javascripts/visits.js.coffee b/app/assets/javascripts/visits.js.coffee new file mode 100644 index 0000000..7615679 --- /dev/null +++ b/app/assets/javascripts/visits.js.coffee @@ -0,0 +1,3 @@ +# Place all the behaviors and hooks related to the matching controller here. +# All this logic will automatically be available in application.js. +# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/ diff --git a/app/assets/stylesheets/visits.css.scss b/app/assets/stylesheets/visits.css.scss new file mode 100644 index 0000000..99b00b9 --- /dev/null +++ b/app/assets/stylesheets/visits.css.scss @@ -0,0 +1,3 @@ +// Place all the styles related to the visits controller here. +// They will automatically be included in application.css. +// You can use Sass (SCSS) here: http://sass-lang.com/ diff --git a/app/controllers/visits_controller.rb b/app/controllers/visits_controller.rb new file mode 100644 index 0000000..fb82b60 --- /dev/null +++ b/app/controllers/visits_controller.rb @@ -0,0 +1,83 @@ +class VisitsController < ApplicationController + # GET /visits + # GET /visits.json + def index + @visits = Visit.all + + respond_to do |format| + format.html # index.html.erb + format.json { render json: @visits } + end + end + + # GET /visits/1 + # GET /visits/1.json + def show + @visit = Visit.find(params[:id]) + + respond_to do |format| + format.html # show.html.erb + format.json { render json: @visit } + end + end + + # GET /visits/new + # GET /visits/new.json + def new + @visit = Visit.new + + respond_to do |format| + format.html # new.html.erb + format.json { render json: @visit } + end + end + + # GET /visits/1/edit + def edit + @visit = Visit.find(params[:id]) + end + + # POST /visits + # POST /visits.json + def create + @visit = Visit.new(params[:visit]) + + respond_to do |format| + if @visit.save + format.html { redirect_to @visit, notice: 'Visit was successfully created.' } + format.json { render json: @visit, status: :created, location: @visit } + else + format.html { render action: "new" } + format.json { render json: @visit.errors, status: :unprocessable_entity } + end + end + end + + # PUT /visits/1 + # PUT /visits/1.json + def update + @visit = Visit.find(params[:id]) + + respond_to do |format| + if @visit.update_attributes(params[:visit]) + format.html { redirect_to @visit, notice: 'Visit was successfully updated.' } + format.json { head :no_content } + else + format.html { render action: "edit" } + format.json { render json: @visit.errors, status: :unprocessable_entity } + end + end + end + + # DELETE /visits/1 + # DELETE /visits/1.json + def destroy + @visit = Visit.find(params[:id]) + @visit.destroy + + respond_to do |format| + format.html { redirect_to visits_url } + format.json { head :no_content } + end + end +end diff --git a/app/helpers/visits_helper.rb b/app/helpers/visits_helper.rb new file mode 100644 index 0000000..8ce5f83 --- /dev/null +++ b/app/helpers/visits_helper.rb @@ -0,0 +1,2 @@ +module VisitsHelper +end diff --git a/app/models/visit.rb b/app/models/visit.rb new file mode 100644 index 0000000..a950b2a --- /dev/null +++ b/app/models/visit.rb @@ -0,0 +1,2 @@ +class Visit < ActiveRecord::Base +end diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 4ee8275..2d16f05 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -44,7 +44,7 @@ <%= link_to "Home", planet_index_path %>
<%= link_to "Tipos", types_path %>
<%= link_to "Sitios", sites_path %>
- <% link_to "Viajes", trips_path %>
+ <%= link_to "Viajes", trips_path %>
<%= link_to "Contact", planet_contact_path %>
<%= link_to "Sign up", new_user_registration_path %> diff --git a/app/views/trips/index.html.erb b/app/views/trips/index.html.erb index 77fb9c5..0354f68 100644 --- a/app/views/trips/index.html.erb +++ b/app/views/trips/index.html.erb @@ -17,7 +17,7 @@ <%= link_to 'Show', trip %>
<% if trip.user == current_user %> - <%= link_to 'Edit', edit_trip_path(type) %>
+ <%= link_to 'Edit', edit_trip_path(trip) %>
<%= link_to 'Destroy', trip, :confirm => 'Are you sure?', :method => :delete %> diff --git a/app/views/visits/_form.html.erb b/app/views/visits/_form.html.erb new file mode 100644 index 0000000..12ab912 --- /dev/null +++ b/app/views/visits/_form.html.erb @@ -0,0 +1,29 @@ +<%= form_for(@visit) do |f| %> + <% if @visit.errors.any? %> +
+

<%= pluralize(@visit.errors.count, "error") %> prohibited this visit from being saved:

+ +
    + <% @visit.errors.full_messages.each do |msg| %> +
  • <%= msg %>
  • + <% end %> +
+
+ <% end %> + +
+ <%= f.label :trip_id %>
+ <%= f.number_field :trip_id %> +
+
+ <%= f.label :site_id %>
+ <%= f.number_field :site_id %> +
+
+ <%= f.label :hour %>
+ <%= f.number_field :hour %> +
+
+ <%= f.submit %> +
+<% end %> diff --git a/app/views/visits/edit.html.erb b/app/views/visits/edit.html.erb new file mode 100644 index 0000000..66d34d9 --- /dev/null +++ b/app/views/visits/edit.html.erb @@ -0,0 +1,6 @@ +

Editing visit

+ +<%= render 'form' %> + +<%= link_to 'Show', @visit %> | +<%= link_to 'Back', visits_path %> diff --git a/app/views/visits/index.html.erb b/app/views/visits/index.html.erb new file mode 100644 index 0000000..c7bea46 --- /dev/null +++ b/app/views/visits/index.html.erb @@ -0,0 +1,27 @@ +

Listing visits

+ + + + + + + + + + + +<% @visits.each do |visit| %> + + + + + + + + +<% end %> +
TripSiteHour
<%= visit.trip_id %><%= visit.site_id %><%= visit.hour %><%= link_to 'Show', visit %><%= link_to 'Edit', edit_visit_path(visit) %><%= link_to 'Destroy', visit, confirm: 'Are you sure?', method: :delete %>
+ +
+ +<%= link_to 'New Visit', new_visit_path %> diff --git a/app/views/visits/new.html.erb b/app/views/visits/new.html.erb new file mode 100644 index 0000000..1be1930 --- /dev/null +++ b/app/views/visits/new.html.erb @@ -0,0 +1,5 @@ +

New visit

+ +<%= render 'form' %> + +<%= link_to 'Back', visits_path %> diff --git a/app/views/visits/show.html.erb b/app/views/visits/show.html.erb new file mode 100644 index 0000000..2bf41f5 --- /dev/null +++ b/app/views/visits/show.html.erb @@ -0,0 +1,20 @@ +

<%= notice %>

+ +

+ Trip: + <%= @visit.trip_id %> +

+ +

+ Site: + <%= @visit.site_id %> +

+ +

+ Hour: + <%= @visit.hour %> +

+ + +<%= link_to 'Edit', edit_visit_path(@visit) %> | +<%= link_to 'Back', visits_path %> diff --git a/config/routes.rb b/config/routes.rb index 480032b..5f26593 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -3,6 +3,8 @@ + resources :visits + resources :trips devise_for :users diff --git a/db/migrate/20120417143006_create_visits.rb b/db/migrate/20120417143006_create_visits.rb new file mode 100644 index 0000000..248b6be --- /dev/null +++ b/db/migrate/20120417143006_create_visits.rb @@ -0,0 +1,11 @@ +class CreateVisits < ActiveRecord::Migration + def change + create_table :visits do |t| + t.integer :trip_id + t.integer :site_id + t.integer :hour + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index eaf86e6..bf99d42 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -11,7 +11,7 @@ # # It's strongly recommended to check this file into your version control system. -ActiveRecord::Schema.define(:version => 20120417103003) do +ActiveRecord::Schema.define(:version => 20120417143006) do create_table "comentarios", :force => true do |t| t.string "coment" @@ -66,4 +66,12 @@ add_index "users", ["email"], :name => "index_users_on_email", :unique => true add_index "users", ["reset_password_token"], :name => "index_users_on_reset_password_token", :unique => true + create_table "visits", :force => true do |t| + t.integer "trip_id" + t.integer "site_id" + t.integer "hour" + t.datetime "created_at", :null => false + t.datetime "updated_at", :null => false + end + end diff --git a/test/fixtures/visits.yml b/test/fixtures/visits.yml new file mode 100644 index 0000000..6a15000 --- /dev/null +++ b/test/fixtures/visits.yml @@ -0,0 +1,11 @@ +# Read about fixtures at http://api.rubyonrails.org/classes/ActiveRecord/Fixtures.html + +one: + trip_id: 1 + site_id: 1 + hour: 1 + +two: + trip_id: 1 + site_id: 1 + hour: 1 diff --git a/test/functional/visits_controller_test.rb b/test/functional/visits_controller_test.rb new file mode 100644 index 0000000..45397e3 --- /dev/null +++ b/test/functional/visits_controller_test.rb @@ -0,0 +1,49 @@ +require 'test_helper' + +class VisitsControllerTest < ActionController::TestCase + setup do + @visit = visits(:one) + end + + test "should get index" do + get :index + assert_response :success + assert_not_nil assigns(:visits) + end + + test "should get new" do + get :new + assert_response :success + end + + test "should create visit" do + assert_difference('Visit.count') do + post :create, visit: @visit.attributes + end + + assert_redirected_to visit_path(assigns(:visit)) + end + + test "should show visit" do + get :show, id: @visit + assert_response :success + end + + test "should get edit" do + get :edit, id: @visit + assert_response :success + end + + test "should update visit" do + put :update, id: @visit, visit: @visit.attributes + assert_redirected_to visit_path(assigns(:visit)) + end + + test "should destroy visit" do + assert_difference('Visit.count', -1) do + delete :destroy, id: @visit + end + + assert_redirected_to visits_path + end +end diff --git a/test/unit/helpers/visits_helper_test.rb b/test/unit/helpers/visits_helper_test.rb new file mode 100644 index 0000000..6f1596c --- /dev/null +++ b/test/unit/helpers/visits_helper_test.rb @@ -0,0 +1,4 @@ +require 'test_helper' + +class VisitsHelperTest < ActionView::TestCase +end diff --git a/test/unit/visit_test.rb b/test/unit/visit_test.rb new file mode 100644 index 0000000..a34aa33 --- /dev/null +++ b/test/unit/visit_test.rb @@ -0,0 +1,7 @@ +require 'test_helper' + +class VisitTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end From 3486210a35ed8cf4e333a559207ba41d6b3edb38 Mon Sep 17 00:00:00 2001 From: lmargal06 Date: Sun, 22 Apr 2012 16:29:54 +0200 Subject: [PATCH 12/14] Entrega7 --- app/assets/stylesheets/planet.css | 10 ++ app/controllers/comentarios_controller.rb | 2 +- app/controllers/planet_controller.rb | 4 + app/controllers/trips_controller.rb | 1 + app/controllers/types_controller.rb | 2 + app/controllers/visits_controller.rb | 9 +- app/models/site.rb | 3 +- app/models/trip.rb | 2 + app/models/visit.rb | 2 + app/views/comentarios/index.html.erb | 2 +- app/views/layouts/application.html.erb | 110 +++++++++++++++++++++- app/views/planet/search.html.erb | 75 +++++++++++++++ app/views/sites/_form.html.erb | 14 +++ app/views/sites/index.html.erb | 2 +- app/views/sites/new.html.erb | 9 ++ app/views/sites/show.html.erb | 30 +++++- app/views/trips/_trip.html.erb | 31 ++++++ app/views/trips/show.html.erb | 81 ++++++++++++---- config/routes.rb | 2 +- db/migrate/20120415172636_user_sites.rb | 4 +- db/migrate/20120418174404_geo_loc.rb | 17 ++++ db/schema.rb | 5 +- 22 files changed, 380 insertions(+), 37 deletions(-) create mode 100644 app/views/planet/search.html.erb create mode 100644 app/views/trips/_trip.html.erb create mode 100644 db/migrate/20120418174404_geo_loc.rb diff --git a/app/assets/stylesheets/planet.css b/app/assets/stylesheets/planet.css index b0555ed..9ec3db0 100644 --- a/app/assets/stylesheets/planet.css +++ b/app/assets/stylesheets/planet.css @@ -9,6 +9,10 @@ font: bold smaller sans-serif; } +#comentarios a {font-weight:bold; + color:black; + font: 105% sans-serif; + } #links a { color : #555;} #links { @@ -19,6 +23,12 @@ margin-bottom: 10px; word-spacing:25pt; } +#map_canvas { + height: 300pt; + width: 300pt; + } + + #cv {font:sans-serif;} diff --git a/app/controllers/comentarios_controller.rb b/app/controllers/comentarios_controller.rb index f499da7..63b96ce 100644 --- a/app/controllers/comentarios_controller.rb +++ b/app/controllers/comentarios_controller.rb @@ -8,7 +8,7 @@ def index @comentarios = Site.find(params[:site_id]).comentarios # path: /types/id/sites - @comentario = current_user.comentarios.build + diff --git a/app/controllers/planet_controller.rb b/app/controllers/planet_controller.rb index 14af13e..10f5b3d 100644 --- a/app/controllers/planet_controller.rb +++ b/app/controllers/planet_controller.rb @@ -4,6 +4,10 @@ class PlanetController < ApplicationController def index end +def search + @sites= Site.where("name like ? or description like ?" , "%" + params[:busqueda] + "%" , "%" + params[:busqueda] + "%") + @trips= Trip.where("name like ? or description like ?" , "%" + params[:busqueda] + "%" , "%" + params[:busqueda] + "%") + end # GET /planet/contact def contact diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index 3764486..56cc227 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -16,6 +16,7 @@ def index # GET /trips/1.json def show @trip = Trip.find(params[:id]) + @visit= @trip.visits.build respond_to do |format| format.html # show.html.erb diff --git a/app/controllers/types_controller.rb b/app/controllers/types_controller.rb index e8776c1..68bc419 100644 --- a/app/controllers/types_controller.rb +++ b/app/controllers/types_controller.rb @@ -53,6 +53,8 @@ def create end end + + # PUT /types/1 # PUT /types/1.json def update diff --git a/app/controllers/visits_controller.rb b/app/controllers/visits_controller.rb index fb82b60..96ad293 100644 --- a/app/controllers/visits_controller.rb +++ b/app/controllers/visits_controller.rb @@ -44,7 +44,8 @@ def create respond_to do |format| if @visit.save - format.html { redirect_to @visit, notice: 'Visit was successfully created.' } + + format.html { redirect_to @visit.trip, notice: 'Visit was successfully created.' } format.json { render json: @visit, status: :created, location: @visit } else format.html { render action: "new" } @@ -60,7 +61,8 @@ def update respond_to do |format| if @visit.update_attributes(params[:visit]) - format.html { redirect_to @visit, notice: 'Visit was successfully updated.' } + + format.html { redirect_to @visit.trip, notice: 'Visit was successfully updated.' } format.json { head :no_content } else format.html { render action: "edit" } @@ -76,7 +78,8 @@ def destroy @visit.destroy respond_to do |format| - format.html { redirect_to visits_url } + + format.html { redirect_to @visit.trip } format.json { head :no_content } end end diff --git a/app/models/site.rb b/app/models/site.rb index f9b93cf..2c9fab0 100644 --- a/app/models/site.rb +++ b/app/models/site.rb @@ -2,7 +2,8 @@ class Site < ActiveRecord::Base belongs_to :type belongs_to :user has_many :comentarios - + has_many :visits + has_many :trips, :through => :visits # Debe estar protegido para evitar accesos indeseados diff --git a/app/models/trip.rb b/app/models/trip.rb index 6f517ed..a175941 100644 --- a/app/models/trip.rb +++ b/app/models/trip.rb @@ -1,5 +1,7 @@ class Trip < ActiveRecord::Base belongs_to :user + has_many :visits + has_many :sites, :through => :visits attr_protected :user_id #Por Seguridad end diff --git a/app/models/visit.rb b/app/models/visit.rb index a950b2a..ca23b73 100644 --- a/app/models/visit.rb +++ b/app/models/visit.rb @@ -1,2 +1,4 @@ class Visit < ActiveRecord::Base + belongs_to :trip + belongs_to :site end diff --git a/app/views/comentarios/index.html.erb b/app/views/comentarios/index.html.erb index 2f9a38e..d3dd34b 100644 --- a/app/views/comentarios/index.html.erb +++ b/app/views/comentarios/index.html.erb @@ -20,7 +20,7 @@ - + <% if comentario.user == current_user %>

<%= link_to 'Eliminar', [comentario.site, comentario], diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 2d16f05..50fd84b 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -6,13 +6,109 @@ <%= javascript_include_tag "application" %> <%= csrf_meta_tags %> - + + + }); + + +// Success callback function + +function writePosition(pos) { + + var mylat = pos.coords.latitude; + var mylong = pos.coords.longitude; + +$('#site_latitud').val(mylat); //escribo la latitud en el formulario para crear sitio + +$('#site_longitud').val(mylong); + + + + +} + + + +function displayPosition(latitud , longitud , zom) { + + if(latitud.length == null) { + var mylat = latitud; + var mylong = longitud; + + } else { + +var mylat = latitud[0]; + var mylong = longitud[0]; + + + } + var thediv = document.getElementById('locationinfo'); + thediv.innerHTML = '

La localización exacta es longitud: ' + + mylong + ' y latitud: ' + mylat + '

'; + +//Load Google Map + + var latlng = new google.maps.LatLng(mylat, mylong); + + var myOptions = { + zoom: zom, + center: latlng, + mapTypeId: google.maps.MapTypeId.ROADMAP + }; + + var map = new google.maps.Map(document.getElementById("map_canvas"), myOptions); + +//Add marker +if(latitud.length != null) { +for(var i=0; i + + +